Python不写头

Python不写头,python,python-2.7,csv,python-3.x,Python,Python 2.7,Csv,Python 3.x,我使用这个python程序基于第二列“ParentID”拆分了一个非常大的csv。我最近更新为“a”而不是“w”,因为有大量的文件和每个进程的限制。在这样做的过程中,我的头文件每次都在写入,而不仅仅是第一次写入每个文件 我更新为添加“write_header=true”和“write_header=false”,但现在它只在第一个文件上写入头。。。我有超过29000个文件 #!/usr/bin/env python3 import binascii import csv import os.pa

我使用这个python程序基于第二列“ParentID”拆分了一个非常大的csv。我最近更新为“a”而不是“w”,因为有大量的文件和每个进程的限制。在这样做的过程中,我的头文件每次都在写入,而不仅仅是第一次写入每个文件

我更新为添加“write_header=true”和“write_header=false”,但现在它只在第一个文件上写入头。。。我有超过29000个文件

#!/usr/bin/env python3
import binascii
import csv
import os.path
import sys
from tkinter.filedialog import askopenfilename, askdirectory
from tkinter.simpledialog import askinteger

def split_csv_file(f, dst_dir, keyfunc):
    csv_reader = csv.reader(f)
    header = next(csv_reader)
    write_header = True
    csv_writers = {}
    for row in csv_reader:
        k = keyfunc(row)
        with open(os.path.join(dst_dir, k), mode='a', newline='') as output:
            writer = csv.writer(output)
            while write_header:
                writer.writerow(header)
                write_header = False
            csv_writers[k] = writer
            csv_writers[k].writerow(row[0:1])

def get_args_from_cli():
    input_filename = sys.argv[1]
    column = int(sys.argv[2])
    dst_dir = sys.argv[3]
    return (input_filename, column, dst_dir)

def get_args_from_gui():
    input_filename = askopenfilename(
        filetypes=(('TXT','.txt'),('CSV', '.csv')),
        title='Select CSV Input File')
    column = askinteger('Choose Table Column', 'Table column')
    dst_dir = askdirectory(title='Select Destination Directory')
    return (input_filename, column, dst_dir)

if __name__ == '__main__':
    if len(sys.argv) == 1:
        input_filename, column, dst_dir = get_args_from_gui()
    elif len(sys.argv) == 4:
        input_filename, column, dst_dir = get_args_from_cli()
    else:
         raise Exception("Invalid number of arguments")
    with open(input_filename, mode='r', newline='') as f:
        split_csv_file(f, dst_dir, lambda r: r[column-1]+'.txt')
        # if the column has funky values resulting in invalid filenames
        # replace the line from above with:
        # split_csv_file(f, dst_dir, lambda r: binascii.b2a_hex(r[column-1].encode('utf-8')).decode('utf-8')+'.csv')
下面是正在拆分的文件的示例

<option value=''>Choose SubGroup</option>, ParentID
<option value='/1990-Accord-DX-Glass-s/37918.htm'>Glass</option>,Accord1990DX422F22A1BodyHardwareBackGlass
<option value='/1990-Accord-DX-Glass-s/37919.htm'>Glass</option>,Accord1990DX422F22A1BodyHardwareBackGlass
<option value='/1990-Accord-DX-Reveal-Moldings-s/69090.htm'>Reveal Moldings</option>,Accord1990DX422F22A1BodyHardwareBackGlass
<option value='/1990-Accord-DX-Reveal-Moldings-s/69091.htm'>Reveal Moldings</option>,Accord1990DX422F22A1BodyHardwareBackGlass
<option value='/1990-Accord-DX-Center-s/10331.htm'>Center</option>,Accord1990DX422F22A1BodyHardwareConsole
<option value='/1990-Accord-DX-Cowl-s/16006.htm'>Cowl</option>,Accord1990DX422F22A1BodyHardwareCowl
<option value='/1990-Accord-DX-Exterior-Trim-s/26889.htm'>Exterior Trim</option>,Accord1990DX422F22A1BodyHardwareFender
<option value='/1990-Accord-DX-Exterior-Trim-s/26890.htm'>Exterior Trim</option>,Accord1990DX422F22A1BodyHardwareFender
选择子组,父ID
玻璃,手风琴1990DX422F22A11车身硬件背景玻璃
玻璃,手风琴1990DX422F22A11车身硬件背景玻璃
露出模塑件,手风琴1990DX422F22A11车身硬件背景玻璃
露出模塑件,手风琴1990DX422F22A11车身硬件背景玻璃
中心,手风琴1990DX422F22A1BodyHardwareConole
风帽,手风琴1990DX422F22A1BodyHardwareCowl
外部装饰件,手风琴1990DX422F22A1BodyHardwareFinder
外部装饰件,手风琴1990DX422F22A1BodyHardwareFinder

如何使头在每个输出文件上只写入一次?

您第一次写入头时将
write\u header
设置为false。因此,只有打开的第一个文件才能获得该头文件

跟踪哪些文件在集合中设置了标头:

def split_csv_file(f, dst_dir, keyfunc):
    csv_reader = csv.reader(f)
    header = next(csv_reader)
    header_written = set()
    for row in csv_reader:
        k = keyfunc(row)
        with open(os.path.join(dst_dir, k), mode='a', newline='') as output:
            writer = csv.writer(output)
            if k not in header_written:
                writer.writerow(header)
                header_written.add(k)
        writer.writerow(row[0:1])

您可能希望通过跟踪上次写入文件的时间并关闭未写入文件的时间来延长文件的打开时间。这就需要一个自定义类,它可以在您按键请求文件时透明地跟踪文件,这比答案中的工作量要大得多

这是有道理的。。然而,我对python还不熟悉,所以我的理解有点不清楚,所以我只是尝试了您的代码,收到了以下错误:回溯(最近一次调用):文件“”,第14行,在split_csv_File ValueError中:对关闭的文件执行I/O操作。在处理上述异常的过程中,发生了另一个异常:回溯(最近一次调用):文件“”,第9行,在文件“”中,第17行,在拆分\u csv\u文件属性错误:“\u csv.writer”对象没有属性“close”>>>啊,是的;我犯了两个错误:我把
语句放在一起,忘了单独存储文件。请稍后更正。我看到您的编辑。非常感谢。但这让我回到了起点。我收到了相同的“打开的文件太多”错误,这就是为什么我切换到“打开”的原因。是否有办法以这种方式运行它并关闭该文件,如果该txt文件出现另一个实例,则关闭该文件并重新打开。它似乎正是我所需要的。啊,我想你有一个开放文件限制的问题。您可以返回使用append并重新打开文件,但使用字典跟踪文件是否已经写入了头。进一步的改进是仅在接近限制时关闭文件。