使用Python将CSV文件按行拆分为多个独立文件并妥善管理

使用python将csv文件按行拆分为多个独立文件并妥善管理

本文详细介绍了如何使用Python的csv模块将一个大型CSV文件中的每一行数据拆分并写入到单独的CSV文件中。核心内容包括利用csv.writer正确处理CSV格式,以及通过contextlib.ExitStack和字典管理多个文件写入器,以高效、健壮地解决文件名冲突和资源管理问题,确保数据准确无误地分散到指定的新文件中。

1. CSV数据拆分与写入基础

在Python中处理CSV文件时,如果需要将原始文件中的每一行或特定行的数据提取出来,并保存到以行内容命名的独立CSV文件中,一个常见的需求是将特定字段作为新文件的文件名,并将其他字段写入到这个新文件中。

假设我们有一个包含Order Number、Date和File Name三列的CSV文件,目标是为每一行创建一个新的CSV文件,文件名取自File Name字段,新文件中只包含Order Number和Date字段,且不带表头。

最初尝试可能直接使用f.write()方法将字段内容写入文件。然而,这种方法存在一个核心问题:f.write()仅仅是写入字符串,它不会自动添加CSV文件所需的字段分隔符(如逗号)。这会导致所有字段内容被连接成一个单一的字符串,而不是以逗号分隔的多个字段。

错误示例(仅供理解问题,不建议使用):

立即学习“Python免费学习笔记(深入)”;

import csv# 假设TestExport.csv存在于指定路径# with open("//server2/shared/Data/TestExport.csv",'r') as csvfile:#         reader = csv.DictReader(csvfile)#         for row in reader:#             file_name ='{0}.csv'.format(row['FileName'])#             with open(file_name, 'w') as f:#                    f.write(row['Order Number'])#                    f.write(row['Date'])

上述代码的问题在于f.write(row[‘Order Number’])和f.write(row[‘Date’])会将两个字符串直接连接起来,例如123452023-01-01,而不是12345,2023-01-01。

2. 使用csv.writer正确写入CSV数据

解决上述问题的关键在于使用Python内置csv模块提供的csv.writer对象。csv.writer专门用于处理CSV格式的写入,它能够自动处理字段分隔符和行结束符。

核心改进点:

csv.writer(out_f, delimiter=’,’): 创建一个CSV写入器,并指定逗号作为字段分隔符。writer.writerow([…]): 使用此方法写入一行数据。它接受一个列表作为参数,列表中的每个元素将作为一个字段写入,并自动添加分隔符。newline=”: 在打开文件时,对于csv.writer,必须指定newline=”。这是因为csv模块会自行处理换行符,如果Python的默认换行转换机制也介入,可能会导致文件中出现双重换行,或在不同操作系统间产生兼容性问题。

正确实现示例:

import csv# 假设TestExport.csv是你的源文件source_csv_path = "//server2/shared/Data/TestExport.csv"with open(source_csv_path, 'r', encoding='utf-8') as in_f: # 建议指定编码    reader = csv.DictReader(in_f)    for row in reader:        # 根据'FileName'字段生成新CSV的文件名        file_name = '{0}.csv'.format(row['FileName'])        # 以写入模式打开新文件,并指定newline=''        with open(file_name, 'w', newline='', encoding='utf-8') as out_f: # 建议指定编码            # 创建csv写入器,指定逗号为分隔符            writer = csv.writer(out_f, delimiter=',')            # 写入Order Number和Date字段。writerow接受一个列表            writer.writerow([row['Order Number'], row['Date']])print("所有行已成功拆分并写入独立CSV文件。")

这段代码能够正确地将每一行数据拆分并写入到各自的CSV文件中,每个新文件只包含Order Number和Date两个字段,并以逗号分隔。

3. 处理文件名冲突与资源管理:使用contextlib.ExitStack

上述解决方案虽然正确,但存在一个潜在问题:如果源CSV文件中有两行或多行具有相同的File Name字段值,那么后一行的数据将覆盖前一行的数据,因为每次循环都会重新打开并清空同名文件。此外,频繁地打开和关闭文件也可能影响性能。

为了解决这个问题,我们可以采用更高级的策略:

复用写入器: 使用一个字典来存储已经创建的csv.writer对象。当遇到一个已存在文件名的行时,直接使用字典中对应的写入器追加数据,而不是重新创建文件。统一文件管理: 由于我们会打开多个文件并保持它们处于打开状态以供复用,我们需要一种机制来确保所有这些文件最终都能被正确关闭。contextlib.ExitStack是处理这种情况的理想工具。它允许你在一个with语句块中管理多个上下文管理器(如文件对象),并在with块结束时自动关闭所有被管理的资源。

健壮的解决方案示例:

import csvimport contextlibsource_csv_path = "//server2/shared/Data/TestExport.csv"with open(source_csv_path, 'r', encoding='utf-8') as in_f:    # writers字典用于存储每个文件对应的csv.writer对象    # 键是文件名,值是对应的csv.writer实例    writers = {}    # 使用ExitStack来管理所有打开的文件对象    with contextlib.ExitStack() as stack:        reader = csv.DictReader(in_f)        for row in reader:            file_name = '{0}.csv'.format(row['FileName'])            # 尝试从writers字典中获取当前文件名的写入器            writer = writers.get(file_name)            # 如果该文件名的写入器尚未创建            if writer is None:                # 使用stack.enter_context()打开新文件。                # ExitStack会负责在with块结束时关闭此文件。                out_f = stack.enter_context(open(file_name, 'w', newline='', encoding='utf-8'))                # 创建新的csv写入器并存储到writers字典中                writer = csv.writer(out_f)                writers[file_name] = writer                # (可选)为新创建的文件写入表头                # 如果不需要表头,可以删除下面这行                writer.writerow(['OrderNumber', 'Date'])            # 使用获取到的(或新创建的)写入器写入数据行            writer.writerow([row['Order Number'], row['Date']])print("所有行已成功拆分并写入独立CSV文件,重复文件名的数据已追加。")

4. 代码详解与注意事项

contextlib.ExitStack: 这是一个强大的上下文管理器。通过stack.enter_context(resource),你可以将任何上下文管理器(如open()返回的文件对象)注册到ExitStack中。当最外层的with contextlib.ExitStack() as stack:块结束时,无论以何种方式(正常退出、异常),ExitStack都会确保所有注册的资源按LIFO(后进先出)顺序被正确关闭。这避免了手动管理多个文件句柄的复杂性。writers 字典: 这个字典是实现写入器复用的关键。它将文件名映射到对应的csv.writer对象。当处理一行数据时,程序首先检查writers中是否已有该文件名的写入器。如果没有,就创建一个新的文件和写入器,并将其添加到字典中;如果已经存在,则直接使用已有的写入器进行写入。可选的表头写入: 在if writer is None:块中,我们可以在文件首次被创建时写入一个表头(writer.writerow([‘OrderNumber’, ‘Date’]))。这确保了每个新生成的CSV文件都有一个清晰的表头,并且表头只会被写入一次。如果不需要表头,可以删除这行代码。编码(encoding=’utf-8’): 在打开文件时,显式指定编码是一个好习惯,尤其是处理包含非ASCII字符的数据时,utf-8是推荐的通用编码。性能: 相比于每次循环都打开和关闭文件,使用ExitStack和写入器复用可以显著提高处理大量数据时的性能,因为它减少了文件I/O操作的开销。

总结

通过本教程,我们学习了如何使用Python的csv模块将一个CSV文件按行拆分为多个独立的CSV文件。从基础的csv.writer使用到更高级的contextlib.ExitStack和字典组合,我们解决了文件名冲突和资源管理问题,确保了数据拆分过程的准确性、健壮性和高效性。掌握这些技术将帮助你在处理CSV数据时更加灵活和专业。

以上就是使用Python将CSV文件按行拆分为多个独立文件并妥善管理的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1372581.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月14日 12:26:16
下一篇 2025年12月14日 12:26:33

相关推荐

  • Go 语言:编译型语言及其底层原理

    Go 语言是一种编译型语言,它将源代码直接编译成特定平台的可执行文件,无需额外的运行时环境或虚拟机。其高效的编译速度和生成独立可执行文件的特性,使其在系统级编程和服务器端开发领域具有显著优势。 Go 语言的设计目标是提供一种高效、简洁、可靠的编程语言,特别适用于构建大型分布式系统。与解释型语言(如 …

    好文分享 2025年12月15日
    000
  • Go 语言是解释型语言还是编译型语言?

    Go 语言是一种编译型语言,它直接将源代码编译成目标机器上的机器码,生成可独立执行的二进制文件,无需任何额外的运行时环境或依赖。Go 编译器以编译速度快而闻名,并支持多种操作系统和架构。 Go 语言的设计目标之一就是提供一种高效且易于部署的编程语言。为了实现这一目标,Go 语言采用了编译型模型,这意…

    2025年12月15日
    000
  • Go 语言是解释型还是编译型?深入理解 Go 的编译过程

    本文旨在解答 Go 语言的编译方式,明确 Go 语言属于编译型语言,而非解释型语言。Go 编译器能够生成完全独立的、无需额外运行时环境的可执行文件,并深入探讨了 Go 编译器的特性、支持的架构以及跨平台编译的便捷性,帮助读者更全面地理解 Go 语言的底层机制。 Go 语言是一种编译型语言,它通过编译…

    2025年12月15日
    000
  • Go 语言是解释型还是编译型?深入理解 Go 编译原理

    Go 语言是一种编译型语言,它将源代码直接编译成机器码,生成可独立执行的二进制文件。这意味着无需任何额外的运行时环境或依赖库,即可在目标平台上运行 Go 程序。Go 编译器以其编译速度快而闻名,并且支持多种操作系统和硬件架构,使其成为构建高性能、可移植应用程序的理想选择。 Go 编译器的架构 Go …

    2025年12月15日
    000
  • Google App Engine Go运行时搜索功能实现指南

    本文旨在为Google App Engine Go运行时提供搜索功能缺失时的解决方案。核心方法包括构建一个RESTful Python%ignore_a_1%服务,由Go应用通过urlfetch进行代理调用,实现数据的索引、查询等操作;或利用第三方搜索服务快速集成。文章将详细探讨两种方案的实现细节、…

    2025年12月15日
    000
  • Go 语言中高效打乱数组的教程

    在 Go 语言中,对数组进行随机排序(打乱)是一个常见的需求。与 Python 等语言不同,Go 标准库并没有直接提供 shuffle 函数。然而,我们可以利用 Fisher-Yates 洗牌算法来实现高效且简洁的数组打乱功能。 本文将深入探讨如何在 Go 语言中实现 Fisher-Yates 算法…

    2025年12月15日
    000
  • Go语言:编译型语言的深度解析与系统级编程能力

    Go语言是一种高效的编译型语言,直接将源代码编译为针对特定架构的自给自足的机器码可执行文件,无需外部运行时或库。它支持多平台编译,以其快速编译和部署能力,成为系统级编程的有力替代者,提供了卓越的性能和部署便利性。 Go语言的编译本质 go语言的核心特性之一是其作为一种编译型语言的定位。与解释型语言(…

    2025年12月15日
    000
  • Go 语言中高效打乱数组的指南

    本文旨在介绍在 Go 语言中如何高效地打乱数组(或切片)的顺序。 重点讲解了 Fisher-Yates shuffle 算法的 Go 语言实现,并提供了避免额外内存分配的优化方案。通过示例代码和详细解释,帮助开发者掌握在 Go 语言中实现数组随机排序的技巧,并理解其背后的原理。 在 Go 语言中,并…

    2025年12月15日
    000
  • Golang encoding/json库JSON序列化与反序列化

    答案是使用Go的encoding/json库通过json.Marshal和json.Unmarshal实现序列化与反序列化,利用结构体标签控制字段映射,omitempty忽略零值字段,优先使用具体结构体而非interface{}以提升性能,并通过检查错误类型实现健壮的错误处理。 Go语言的 enco…

    2025年12月15日
    000
  • Golang反射在RPC调用中参数解析实践

    Golang反射在RPC参数解析中的核心作用是实现运行时动态处理异构请求。通过反射,框架能在不预先知晓具体类型的情况下,根据方法签名动态创建参数实例、反序列化字节流并完成函数调用。具体步骤包括:服务注册与查找、获取方法签名、动态创建参数、反序列化数据、构建调用列表、执行方法及处理返回值。为保障性能,…

    2025年12月15日
    000
  • Golangencoding/base64数据编码与解码方法

    Go语言中base64包提供标准编码解码功能,使用StdEncoding.EncodeToString将字节切片转为Base64字符串,如”Hello, 世界”编码为”SGVsbG8sIOS4lueVjA==”;对于URL场景应选用URLEncodin…

    2025年12月15日
    000
  • GolangHTTP接口性能测试与优化方法

    使用基准测试和压测工具评估性能,通过减少内存分配、优化服务配置、启用pprof分析及高效序列化提升Go HTTP接口性能,可稳定达到数万QPS。 Go语言因其高效的并发模型和简洁的语法,被广泛用于构建高性能HTTP服务。在实际开发中,对接口进行性能测试与优化是保障系统稳定性和响应速度的关键步骤。下面…

    2025年12月15日
    000
  • Golang模块依赖版本选择与更新策略

    Go模块依赖管理需遵循语义化版本规范,采用最小版本选择策略确保稳定性;通过go get指定版本、replace替换源等方式精确控制依赖;结合govulncheck扫描漏洞、测试覆盖和分阶段更新保障安全;利用renovatebot、dependabot等工具实现自动化更新闭环,建议定期评估依赖并建立团…

    2025年12月15日
    000
  • Golang状态模式对象状态管理技巧

    在Go中使用状态模式需定义统一的状态接口与具体状态实现,主体对象通过接口调用行为,实现行为与状态解耦;2. 通过状态转移表集中管理状态切换逻辑,避免重复代码;3. 使用接口方法(如Status)获取状态标识,不依赖字段或类型判断,保证封装性;4. 多goroutine环境下在SetState及行为方…

    2025年12月15日
    000
  • GolangREST API中错误返回规范示例

    答案:Go语言中通过定义统一的错误响应结构体和错误码常量,结合工厂函数与中间件,实现REST API的标准化错误返回,提升前后端协作效率与系统可维护性。 在Go语言构建的REST API中,统一的错误返回格式有助于前端或API调用者快速理解错误原因并做相应处理。以下是一个常见的错误返回规范示例,包含…

    2025年12月15日
    000
  • Golang并发程序单元测试实践

    使用sync.WaitGroup和互斥锁确保并发测试的可预测性,结合context实现超时与取消控制,通过模拟真实场景验证多goroutine行为正确性。 Go语言的并发模型基于goroutine和channel,使得编写高并发程序变得简洁高效。但并发程序的不确定性也给单元测试带来了挑战。要写出可靠…

    2025年12月15日
    000
  • Golang微服务容器化与Docker实践

    Golang微服务通过Docker容器化实现高效部署,结合Kubernetes可提升系统可扩展性与稳定性。 微服务架构让系统更灵活、可扩展,而Go语言(Golang)凭借高并发、低内存占用和快速启动的特性,成为构建微服务的热门选择。结合Docker容器化技术,可以实现服务的标准化打包、快速部署和环境…

    2025年12月15日
    000
  • Go语言中基于自签名证书和公钥校验的安全双向认证连接实现

    本教程详细阐述了如何在Go语言中,利用自签名X.509证书和crypto/tls库,为完全受控的客户端与服务器端建立安全的双向认证连接。文章涵盖了使用OpenSSL生成证书与密钥、配置TLS连接参数、以及通过比对预设公钥实现对等方身份验证的关键步骤,旨在提供一种在非信任网络环境下实现高安全性通信的专…

    2025年12月15日
    000
  • Go语言中构建包含嵌套参数的POST请求

    第一段引用上面的摘要: 本文介绍了在Go语言中如何构建包含嵌套参数的POST请求。由于HTTP协议本身不支持参数嵌套,我们需要手动处理参数的编码和格式化。本文将探讨如何将嵌套的数据结构转换为url.Values类型,并提供相应的示例代码,帮助读者理解和实现这一过程。 理解url.Values类型 在…

    2025年12月15日
    000
  • 使用 Go 发送带有嵌套参数的 POST 请求

    本文旨在帮助 Go 语言初学者理解如何发送带有嵌套参数的 POST 请求。由于 HTTP 协议本身不支持参数嵌套,我们需要通过特定的编码方式来模拟这种结构。本文将介绍如何在 Go 中处理这种情况,并提供示例代码和注意事项。 在 Go 中,net/http 包提供了发送 HTTP 请求的功能。http…

    2025年12月15日
    000

发表回复

登录后才能评论
关注微信