3

这是我在 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 代码会增加那么多时间吗?

4

4 回答 4

9

这里:

for line in f.readlines():

你应该这样做:

for line in f:

前者将整个文件读入一个行列表,然后遍历该列表。后者以增量方式执行此操作,这将大大减少分配的总内存,然后由您的程序释放。

于 2013-02-22T14:06:00.523 回答
2

每当你问“这其中的哪一部分减慢了整个事情的速度?” 答案是“剖析它”。在Python Profilers 的Python 文档中有一个很好的描述如何做到这一点。此外,正如 John Zwinck 指出的那样,您一次将太多内容加载到内存中,并且一次只能加载一行(文件对象在 Python 中是“可迭代的”)。

就个人而言,我更喜欢 Perl 所说的“调度表”,而不是一个巨大的if..elif...elif怪物。 这个网页描述了一种 Pythonic 的方式。它是功能键的字典,并非在所有情况下都有效,但对于简单的if x==2:...elif x==3...(即,切换一个变量的值)来说效果很好。

于 2013-02-22T14:18:27.127 回答
1

使用可迭代(通过使用产量)将更多行“缓冲”到内存中,而不是一次只缓冲一行,而不是一次缓冲整个文件。

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)
于 2013-02-22T18:17:31.057 回答
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'))
于 2013-02-22T18:36:44.030 回答