在Python中同时处理两个文件

时间:2009-11-13 18:47:36

标签: python string

我有关于12340辆汽车的信息。此信息按顺序存储在两个不同的文件中:

  1. car_names.txt,其中包含一行代表每辆车的名称
  2. car_descriptions.txt,其中包含每辆车的说明。因此每行40行,其中第6行读取@CAR_NAME
  3. 我想在python中做:为car_descriptions.txt文件中的每辆车添加第7行中的每辆车的名称(来自其他文件)(它是空的),就在@CAR_NAME <之后/ p>

    我想到了:

    1)读取第一个文件并将汽车名称存储在矩阵/列表中 2)开始阅读第二个文件,每次找到字符串@CAR_NAME,只需在下一行写下名称

    但是我想知道是否有更快的方法,所以程序每次从每个文件读取一行并进行修改。

    由于

6 个答案:

答案 0 :(得分:9)

首先,制作一个从序列中检索汽车名称的发电机。你可以每7行产生一次;我已经让我的产量接近以@CAR_NAME开头的行:

def car_names(seq):
    yieldnext=False
    for line in seq:
        if yieldnext: yield line
        yieldnext = line.startswith('@CAR_NAME')

现在您可以使用itertools.izip并行浏览两个序列:

from itertools import izip
with open(r'c:\temp\cars.txt') as f1:
    with open(r'c:\temp\car_names.txt') as f2:
        for (c1, c2) in izip(f1, car_names(f2)):
            print c1, c2

答案 1 :(得分:8)

我不确定我是否完全理解你要做的事情,是这样的吗?

f1 = open ('car_names.txt')
f2 = open ('car_descriptions.txt')
for car_name in f1.readlines ():
        for i in range (6):   # echo the first 6 lines
                print f2.readline ()
        assert f2.readline() == '@CAR_NAME'  # skip the 7th, but assert that it is @CAR_NAME
        print car_name    # print the real car name
        for i in range (33):  # print the remaining 33 of the original 40
               print f2.readline ()

答案 2 :(得分:4)

阅读car_names.txt将为您节省大量内存(按照今天的标准真的很小;-)但绝对不会比在一口气下sl(更快(最好的情况下,它会完全正确除非您的底层操作系统和存储系统在读取前瞻缓存/缓冲方面做得很好,否则速度可能相同,甚至可能稍慢一些。所以我建议:

import fileinput

carnames = open('car_names.txt').readlines()
carnamit = iter(carnames)

skip = False
for line in fileinput.input(['car_descriptions.txt'], True, '.bak'):
  if not skip:
    print line,
  if '@CAR_NAME' in line:
    print next(carnamit),
    skip = True
  else:
    skip = False

所以测量速度,以及

的替代方案
carnamit = open('car_names.txt')

在开始时而不是像我的第一个版本那样读取列表上的所有行 - 我敢打赌第一个版本(尽可能存在任何可衡量和可重复的差异)将证明更快。

BTW,标准库的fileinput模块记录为here,它确实是一种方便的方式来执行文本文件的“就地虚拟重写”(通常将旧版本保留为备份,只是在case - 但即使机器应该在操作过程中崩溃,旧版本的数据仍然存在,所以从某种意义上说,“重写”在机器崩溃方面原子地运行,一个很好的小触摸;-)

答案 3 :(得分:1)

for line1, line2 in zip(file(filename1), file(filename2)):
    # do your thing

或类似的

答案 4 :(得分:0)

12340不是任何数据(从某种意义上讲,市场上有更大的数据需要处理)。

更好的方法是在sqlite模块中使用build。 如果不使用像CSV这样的简单格式。这是一个有组织的结构。 如果不使用线程,则可以同时处理两个文件。

答案 5 :(得分:0)

我认为这符合这个问题:

  • 它一次读取一行描述文件
  • 当它看到@CAR_NAME时,它仍然会发出它,但用名称文件中的下一行替换描述文件中的下一行

def merge_car_descriptions(namefile, descrfile):
    names = open(namefile,'r')
    descr = open(descrfile,'r')
    for d in descr:
        if '@CAR_NAME' in d:
            yield d + names.readline()
            descr.next()
        else:
            yield d

if __name__=='__main__':
    import sys
    if len(sys.argv) != 3:
        sys.exit("Syntax: %s car_names.txt car_descriptions.txt" % sys.argv[0])
    for l in merge_car_descriptions(sys.argv[1], sys.argv[2]):
        print l,