这是我在Python工作的第二天。我在C ++工作了一段时间,但决定尝试使用Python。我的程序按预期工作。但是,当我在没有glob循环的情况下一次处理一个文件时,每个文件大约需要半个小时。当我包含glob时,循环大约需要12个小时来处理8个文件。
我的问题是,我的程序中有什么东西肯定会减慢速度吗?有什么我应该做的让它更快?
我有一个大文件夹。例如
file1.txt(6gb) file2.txt(5.5gb) file3.txt(6gb)
如果有帮助,每行数据都以一个字符开头,该字符告诉我其余字符是如何格式化的,这就是为什么我有所有if elif语句的原因。一行数据如下所示: T35201 M352 RZNGA AC
我正在尝试读取每个文件,使用拆分进行一些解析,然后保存文件。
计算机有32GB的ram,所以我的方法是将每个文件读入ram,然后遍历文件,然后保存,清除RAM用于下一个文件。
我已经包含了该文件,因此您可以看到我正在使用的方法。我使用if elif语句,它使用大约10个不同的elif命令。我曾经尝试过一本字典,但我无法理解为了挽救我的生命。
任何答案都会有所帮助。
import csv
import glob
for filename in glob.glob("/media/3tb/5may/*.txt"):
f = open(filename,'r')
c = csv.writer(open(filename + '.csv','wb'))
second=0
mill=0
for line in f.readlines():
#print line
event=0
ticker=0
marketCategory=0
variable = line[0:1]
if variable is 'T':
second = line[1:6]
mill=0
else:
second = second
if variable is 'R':
ticker = line[1:7]
marketCategory = line[7:8]
elif variable is ...
elif variable is ...
elif ...
elif ...
elif ...
elif ...
elif
if variable (!= 'T') and (!= 'M')
c.writerow([second,mill,event ....])
f.close()
更新 每个elif语句几乎相同。唯一改变的部分是我分割线条的方式。这里有两个elif语句(总共有13个,除了它们被拆分的方式外几乎都是相同的。)
elif variable is 'C':
order = line[1:10]
Shares = line[10:16]
match = line[16:25]
printable = line[25:26]
price = line[26:36]
elif variable is 'P':
ticker = line[17:23]
order = line[1:10]
buy = line[10:11]
shares = line[11:17]
price = line[23:33]
match = line[33:42]
UPDATE2
我使用for file in f
两次运行代码。我第一次运行单个文件没有 for filename in glob.glob("/media/3tb/file.txt"):
,手动编码一个文件的文件路径花了大约30分钟。
我再次使用 for filename in glob.glob("/media/3tb/*file.txt")
再次运行并且文件夹中的一个文件花了一个小时。 glob代码是否会增加这么多时间?
答案 0 :(得分:9)
下面:
for line in f.readlines():
你应该这样做:
for line in f:
前者将整个文件读入行列表,然后遍历该列表。后者以增量方式执行,这应该大大减少分配的总内存,然后由程序释放。
答案 1 :(得分:2)
每当你问“这件事的哪一部分会减慢整个事情的速度?”答案是“描述它”。在The Python Profilers的Python文档中有一个很好的描述如何执行此操作。另外,正如John Zwinck指出的那样,你一次加载到内存中太多了,应该一次只加载一行(文件对象在Python中是“可迭代的”)。
就个人而言,我更喜欢Perl称之为“调度表”的巨大if..elif...elif
怪物。 This webpage描述了一种Pythonic方法。它是一个函数键的字典,它在所有情况下都不起作用,但对于简单的if x==2:...elif x==3...
(即,切换一个变量的值)它很有用。
答案 2 :(得分:1)
使用iterable(通过使用yield)将更多行缓冲到内存中,而不是一次只有一行,而不是一次整个文件。
def readManyLines(fObj,num=1000):
lines = fObj.readlines(num)
for line in lines:
yield line
f = open(filename,'r')
for line in readManyLines(f):
process(line)
答案 3 :(得分:0)
不确定这是否有帮助,但尝试使用它而不是glob.glob只是为了排除问题所在。我在Windows上,所以我不能100%确定它在unix下工作,但我不明白为什么它不会。
import re
import os
import csv
def find_text_files(root):
"""Find .txt files under a given directory"""
foundFiles = []
for dirpath, dirnames, filenames in os.walk(root):
for file in filenames:
txt = re.compile(r'txt$',re.I,).search(file)
if txt:
foundFiles.append(os.path.join(dirpath,file))
return foundFiles
txtfiles = find_text_files('d:\files') #replace the path with yours
for filename in txtfiles:
f = open(filename,'r')
c = csv.writer(open(filename + '.csv','wb'))