在Python代码中运行“wc -l <文件名>”
我想对一些非常大的文件(每个文件有成千上万行)进行10倍交叉验证。每次开始读取文件时,我想先用“wc -l”命令来统计行数,然后生成固定次数的随机数字,每次把那个行号写入一个单独的文件。我现在使用的是:
import os
for i in files:
os.system("wc -l <insert filename>").
我该如何在这里插入文件名呢?文件名是一个变量。我看过文档,但大部分都是列出ls
命令,这种命令没有这个问题。
7 个回答
4
其实不需要用 wc -l
,可以用下面这个 Python 函数。
def file_len(fname):
with open(fname) as f:
for i, l in enumerate(f, 1):
pass
return i
这个方法可能比调用外部工具要高效,因为它以类似的方式处理输入。
更新
完全错了,wc -l
要快得多!
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
15
让我们来比较一下:
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
开始使用timeit函数吧!
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
所以,在一个大小为150 MB、包含大约500,000个换行符的压缩文件上,wc的速度大约是它的两倍,这是我测试的结果。不过,在一个用seq 3000000 >bigfile
生成的文件上,我得到了这些数字:
wc 0.425990104675
native 0.400163888931
iterate 3.10369205475
嘿,看看,python真厉害!不过,当使用更长的行(大约70个字符)时:
wc 1.60881590843
native 3.24313092232
iterate 4.92839002609
所以结论是:这要看情况,但wc似乎是最好的选择。
8
import subprocess
for f in files:
subprocess.call(['wc', '-l', f])
另外,你可以看看这个链接:http://docs.python.org/library/subprocess.html#convenience-functions。比如说,如果你想把输出结果放到一个字符串里,那么你应该使用 subprocess.check_output()
,而不是 subprocess.call()
。