读取 txt 文件时的性能改进

Performance improvement when reading txt file

我正在寻找我正在做的任务的性能改进。

任务非常简单:从 .txt 文件到 SQL 数据库。

所以 txt 文件由一堆看起来像这样的行组成:

200101 35.922 2.127 1.182 1.182 1.418 1.654

解释:

200111:是信息,包括20 (频道数) 01 (页数) 11 (代码)

其余双精度值只是值:I1、I2...直到 I6

因此,SQL 文件将包含 [channel, page, code, I1, I2, I3, I4, I5, I6, passed]

问题是,在 txt 文件中,code 可以是 00、11、10、01 或 22,并且根据代码,我需要使用这些值执行一个或另一个操作我决定 passed=1 或 passed=0。例如,在这种情况下,如果 code=11passed=1 if I1>I3 and I6<1

txt 中的行按代码排序。

所以,有了这个解释,我基本上就是这样做的:

with open(txtFile, 'r') as txt: 
    for line in txt:
        currentLine = line.split(' ')[0]
        if currentLine.endswith('00'):
            #do some actions here
        if currentLine.endswith('01'):
            #do some actions here
        #...
        #and so on
        # and of course write to SQL file

那么,有没有比用 if 子句检查每一行更好或更省时的方法

你可能只做一次拆分就会得到一些非常轻微的改进:

currentLine = line.split(' ', 1)[0]

或者如果您感兴趣的第一个字段始终具有相同的长度(使用您的示例为 6),您可以尝试仅获取这些字符:

currentLine = line[:6]

如果第一个字段的长度是可变的,你可以试试这个:

currentLine = line[:line.index(' ')]

这里有一些计时,看看哪个更快...

您当前的方法:

# python3 -m timeit -s "l = '200101   35.922    2.127    1.182    1.182    1.418    1.654'" "lineCode = l.split(' ')[0]"
1000000 loops, best of 3: 0.61 usec per loop

第一个建议(限制拆分一次):

# python3 -m timeit -s "l = '200101   35.922    2.127    1.182    1.182    1.418    1.654'" "lineCode = l.split(' ', 1)[0]"
1000000 loops, best of 3: 0.237 usec per loop

第二个建议(使用slice获取定长字段):

# python3 -m timeit -s "l = '200101   35.922    2.127    1.182    1.182    1.418    1.654'" "currentLine = l[:6]"                                                                                             
10000000 loops, best of 3: 0.0708 usec per loop

第三条建议(使用切片+索引获取变长字段):

# python3 -m timeit -s "l = '200101   35.922    2.127    1.182    1.182    1.418    1.654'" "currentLine = l[:l.index(' ')]"
1000000 loops, best of 3: 0.208 usec per loop

在我的初步测试中,如果你能做到,建议 2 似乎是最快的。其他两个建议在性能上非常相似,但比您当前的方法好很多。

显然,这些时间会根据您所使用的平台而有所不同 运行 但相对而言,性能改进应该在任何地方都有效。

现在,综上所述,我同意您的其他评论员的观点,即您的缓慢可能来自其他地方。如果我不得不猜测那将是您的 SQL INSERT。我唯一可以建议做的是,如果数据库和驱动程序允许,或者将您的 SQL 语句写入格式正确的文件并让另一个工具进行批量导入(甚至可以使用 Python 子进程模块)。


其他想法

如果您只需要测试这两个字符(第 5 个和第 6 个),那么这是我发现的最有效的方法。它消除了您正在使用的低效 split 和较慢的 endswith.

你的:

# python3 -m timeit -s "l = '200101   35.922    2.127    1.182    1.182    1.418    1.654'" "currentLine = l.split(' ')[0]; currentLine.endswith('00')"                                                       
1000000 loops, best of 3: 0.72 usec per loop

更好:

# python3 -m timeit -s "l = '200101   35.922    2.127    1.182    1.182    1.418    1.654'" "currentLine = l[:6]; lineCode = currentLine[4:]; lineCode == '00'"
10000000 loops, best of 3: 0.161 usec per loop

最佳:

# python3 -m timeit -s "l = '200101   35.922    2.127    1.182    1.182    1.418    1.654'" "currentLine = l[4:6]; currentLine == '00'"                                                                       
10000000 loops, best of 3: 0.102 usec per loop

所以,你可以这样做:

with open(txtFile, 'r') as txt: 
for line in txt:
    currentLine = line[4:6]
    if currentLine == '00':
        #do some actions here
    elif currentLine == '01':
        #do some actions here
    #...
    #and so on
    # and of course write to SQL file