我想对巨大的文件(每个文件要运行数十万行(进行10倍的交叉验证。我想在每次开始读取文件时做一个"wc-l",然后生成固定次数的随机数,每次都将该行号写入一个单独的文件中。我使用的是:
import os
for i in files:
os.system("wc -l <insert filename>").
如何在那里插入文件名。这是一个变量。我浏览了文档,但它们大多列出了ls
命令,没有这个问题。
让我们比较一下:
from subprocess import check_output
def wc(filename):
return int(check_output(["wc", "-l", filename]).split()[0])
def native(filename):
c = 0
with open(filename) as file:
while True:
chunk = file.read(10 ** 7)
if chunk == "":
return c
c += chunk.count("n")
def iterate(filename):
with open(filename) as file:
for i, line in enumerate(file):
pass
return i + 1
快去计时功能!
from timeit import timeit
from sys import argv
filename = argv[1]
def testwc():
wc(filename)
def testnative():
native(filename)
def testiterate():
iterate(filename)
print "wc", timeit(testwc, number=10)
print "native", timeit(testnative, number=10)
print "iterate", timeit(testiterate, number=10)
结果:
wc 1.25185894966
native 2.47028398514
iterate 2.40715694427
因此,wc在150 MB压缩文件上的速度大约是我测试的速度的两倍,其中有大约50万个换行符。然而,在用seq 3000000 >bigfile
生成的文件上测试时,我得到了以下数字:
wc 0.425990104675
native 0.400163888931
iterate 3.10369205475
嘿,看,蟒蛇FTW!但是,使用较长的行(~70个字符(:
wc 1.60881590843
native 3.24313092232
iterate 4.92839002609
所以结论:这取决于情况,但wc似乎是最好的选择。
import subprocess
for f in files:
subprocess.call(['wc', '-l', f])
还可以看看http://docs.python.org/library/subprocess.html#convenience-函数-例如,如果您想访问字符串中的输出,则需要使用subprocess.check_output()
而不是subprocess.call()
无需使用wc -l
使用以下python函数
def file_len(fname):
with open(fname) as f:
for i, l in enumerate(f, 1):
pass
return i
这可能比调用外部实用程序(以类似的方式在输入上循环(更有效。
更新
大错特错,wc -l
比em>快很多!
seq 10000000 > huge_file
$ time wc -l huge_file
10000000 huge_file
real 0m0.267s
user 0m0.110s
sys 0m0.010s
$ time ./p.py
10000000
real 0m1.583s
user 0m1.040s
sys 0m0.060s
os.system
获取一个字符串。只需显式构建字符串:
import os
for i in files:
os.system("wc -l " + i)
以下是我发现的解决此问题的Python方法:
count_of_lines_in_any_textFile = sum(1 for l in open('any_textFile.txt'))
我发现了一种更简单的方法:
import os
linux_shell='more /etc/hosts|wc -l'
linux_shell_result=os.popen(linux_shell).read()
print(linux_shell_result)
我的解决方案与lazyr的"原生"功能非常相似:
import functools
def file_len2(fname):
with open(fname, 'rb') as f:
lines= 0
reader= functools.partial(f.read, 131072)
for datum in iter(reader, ''):
lines+= datum.count('n')
last_wasnt_nl= datum[-1] != 'n'
return lines + last_wasnt_nl
与wc
不同,这将以'\n'结尾的最后一行而非视为单独的一行。如果想要与wc相同的功能,那么它可以(非常不符合语法:(写成:
import functools as ft, itertools as it, operator as op
def file_len3(fname):
with open(fname, 'rb') as f:
reader= ft.partial(f.read, 131072)
counter= op.methodcaller('count', 'n')
return sum(it.imap(counter, iter(reader, '')))
在我生成的所有测试文件中具有与CCD_ 9相当的时间。
注意:这适用于Windows和POSIX机器。旧的MacOS使用'\r'作为行尾字符。