gpt4 book ai didi

python - 按列连接多个文件的最快方法 - Python

转载 作者:太空狗 更新时间:2023-10-30 01:06:07 25 4
gpt4 key购买 nike

按列连接多个文件的最快方法是什么(在 Python 中)?

假设我有两个文件,每行 1,000,000,000 行,每行约 200 个 UTF8 字符。

方法一:paste作弊

我可以在 linux 系统下通过在 shell 中使用 paste 连接两个文件,我可以使用 os.system 作弊,即:

def concat_files_cheat(file_path, file1, file2, output_path, output):
file1 = os.path.join(file_path, file1)
file2 = os.path.join(file_path, file2)
output = os.path.join(output_path, output)
if not os.path.exists(output):
os.system('paste ' + file1 + ' ' + file2 + ' > ' + output)

方法 2: 使用带有 zip 的嵌套上下文管理器:

def concat_files_zip(file_path, file1, file2, output_path, output):
with open(output, 'wb') as fout:
with open(file1, 'rb') as fin1, open(file2, 'rb') as fin2:
for line1, line2 in zip(fin1, fin2):
fout.write(line1 + '\t' + line2)

方法三:使用fileinput

fileinput 是否并行遍历文件?或者他们会依次遍历每个文件吗?

如果是前者,我会假设它看起来像这样:

def concat_files_fileinput(file_path, file1, file2, output_path, output):
with fileinput.input(files=(file1, file2)) as f:
for line in f:
line1, line2 = process(line)
fout.write(line1 + '\t' + line2)

方法 4:将它们视为 csv

with open(output, 'wb') as fout:
with open(file1, 'rb') as fin1, open(file2, 'rb') as fin2:
writer = csv.writer(w)
reader1, reader2 = csv.reader(fin1), csv.reader(fin2)
for line1, line2 in zip(reader1, reader2):
writer.writerow(line1 + '\t' + line2)

给定数据大小,哪个最快?

为什么一个人会选择一个而不是另一个?我会丢失或添加信息吗?

对于每种方法,除了 \t 之外,我该如何选择不同的分隔符?

还有其他方法可以实现相同的串联列吗?它们一样快吗?

最佳答案

在所有四种方法中,我会选择第二种。但你必须照顾实现中的小细节。(经过一些改进,它需要 0.002 秒,而原始实现大约需要 6 秒;我正在处理的文件是 1M 行;但如果文件大了 1K 倍,因为我们几乎没有使用内存)。

原始实现的变化:

  • 尽可能使用迭代器,否则会消耗内存并且您必须一次处理整个文件。(主要是如果您使用的是 python 2,而不是使用 zip,请使用 itertools.izip)
  • 当你连接字符串时,使用 "%s%s".format() 或类似的;否则你每次都会生成一个新的字符串实例。
  • 没有必要在for里面逐行写。您可以在写入中使用迭代器。
  • 小缓冲区非常有趣,但如果我们使用迭代器,差异非常小,但如果我们尝试一次获取所有数据(例如,我们放置 f1.readlines(1024*1000),它会慢得多).

例子:

def concat_iter(file1, file2, output):
with open(output, 'w', 1024) as fo, \
open(file1, 'r') as f1, \
open(file2, 'r') as f2:
fo.write("".join("{}\t{}".format(l1, l2)
for l1, l2 in izip(f1.readlines(1024),
f2.readlines(1024))))

Profiler 原解。

我们看到最大的问题是写入和压缩(主要是因为不使用迭代器并且必须处理/处理内存中的所有文件)。

~/personal/python-algorithms/files$ python -m cProfile sol_original.py 
10000006 function calls in 5.208 seconds

Ordered by: standard name

ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 5.208 5.208 sol_original.py:1(<module>)
1 2.422 2.422 5.208 5.208 sol_original.py:1(concat_files_zip)
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
**9999999 1.713 0.000 1.713 0.000 {method 'write' of 'file' objects}**
3 0.000 0.000 0.000 0.000 {open}
1 1.072 1.072 1.072 1.072 {zip}

分析器:

~/personal/python-algorithms/files$ python -m cProfile sol1.py 
3731 function calls in 0.002 seconds

Ordered by: standard name

ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.002 0.002 sol1.py:1(<module>)
1 0.000 0.000 0.002 0.002 sol1.py:3(concat_iter6)
1861 0.001 0.000 0.001 0.000 sol1.py:5(<genexpr>)
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
1860 0.001 0.000 0.001 0.000 {method 'format' of 'str' objects}
1 0.000 0.000 0.002 0.002 {method 'join' of 'str' objects}
2 0.000 0.000 0.000 0.000 {method 'readlines' of 'file' objects}
**1 0.000 0.000 0.000 0.000 {method 'write' of 'file' objects}**
3 0.000 0.000 0.000 0.000 {open}

在 python 3 中甚至更快,因为迭代器是内置的,我们不需要导入任何库。

~/personal/python-algorithms/files$ python3.5 -m cProfile sol2.py 
843 function calls (842 primitive calls) in 0.001 seconds
[...]

而且很高兴看到内存消耗和文件系统访问证实了我们之前所说的:

$ /usr/bin/time -v python sol1.py
Command being timed: "python sol1.py"
User time (seconds): 0.01
[...]
Maximum resident set size (kbytes): 7120
Average resident set size (kbytes): 0
Major (requiring I/O) page faults: 0
Minor (reclaiming a frame) page faults: 914
[...]
File system outputs: 40
Socket messages sent: 0
Socket messages received: 0


$ /usr/bin/time -v python sol_original.py
Command being timed: "python sol_original.py"
User time (seconds): 5.64
[...]
Maximum resident set size (kbytes): 1752852
Average resident set size (kbytes): 0
Major (requiring I/O) page faults: 0
Minor (reclaiming a frame) page faults: 427697
[...]
File system inputs: 0
File system outputs: 327696

关于python - 按列连接多个文件的最快方法 - Python,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39888949/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com