针对庞大的串联文件/循环优化脚本,以丢弃文件列表中的缺陷项

时间:2018-06-22 19:19:00

标签: python split itertools

EDIT:用真实示例替换示例文件;将nbratoms变量替换为nbrbonds

初学者问题。

我想针对大型文件(100G +)优化以下脚本。我昨天发现了itertools的存在,但是没有任何线索。

f = open(sys.argv[1], "r")
out = open(sys.argv[2], 'w')

lines = f.read().split('\n@<TRIPOS>MOLECULE')

for i in lines: 
    ii=i.split('\n@<TRIPOS>',4) 
    header=ii[0]
    infos=header.split('\n')[2]
    nbrbonds=infos.split(' ')[2]
    if str(nbrbonds) in ii[2]:
        out.write('\n@<TRIPOS>MOLECULE'+str(i))

out.close()
f.close()

处理后的文件由200,000个以上的串联MOL2文件组成(下面的最后一个示例)。 该脚本的思想是首先将输入文件拆分为两个@<TRIPOS>MOLECULE(=新MOL2文件的第一行)分隔的项目;然后根据以@<TRIPOS>开头的行将这些项目分成4部分(即@<TRIPOS>MOLECULE@<TRIPOS>ATOM@<TRIPOS>BOND@<TRIPOS>ALT_TYPE)。对于每个单个MOL2文件,我想检查标头中(第二个)14(每个单个MOL2文件中的不同)的位置处的值

@<TRIPOS>MOLECULE
Z1198223644
14 14 0 0 0
USER_CHARGES

出现在单个文件的第三部分(以下):

@<TRIPOS>BOND
1       1       2 1
2       2       3 1
3       2       4 1
4       2       5 1
5       5       6 ar
6       5      11 ar
 ...

如果有,则->以\n@<TRIPOS>MOLECULE作为第一行将其打印到outputfile(本质上就是单个MOL2文件的外观)。 它似乎可以正常工作,但是我担心它太业余了。另外,我不知道如何执行避免输出文件以这样的双头标记开头的步骤

@<TRIPOS>MOLECULE@<TRIPOS>MOLECULE
Z1198223644
...

欢迎任何帮助!我加入了一个file,其中包含6个串联的MOL2文件;奇数文件是正确的;甚至文件-错误。

@<TRIPOS>MOLECULE
Z1198223644
14 14 0 0 0
USER_CHARGES
@<TRIPOS>ATOM
  1 F1         23.5932    2.0831  -52.2012 F      1 LIG      -0.15900
  2 C2         22.4195    1.3866  -52.4217 C.3    1 LIG       0.88300
  3 F3         22.5324    0.1265  -51.8643 F      1 LIG      -0.15900
  4 F4         21.3805    2.0570  -51.7993 F      1 LIG      -0.15900
  5 C5         22.1912    1.2555  -53.9016 C.ar   1 LIG       0.04500
  6 C6         21.0466    1.7681  -54.5284 C.ar   1 LIG      -0.13400
  7 C7         20.8964    1.6126  -55.9046 C.ar   1 LIG      -0.19400
  8 C8         21.8881    0.9505  -56.6271 C.ar   1 LIG       0.20700
  9 O9         21.7710    0.7997  -57.8724 O.2    1 LIG      -0.49500
 10 N10        22.9825    0.4691  -55.9778 N.ar   1 LIG       0.11300
 11 N11        23.1254    0.6186  -54.6592 N.ar   1 LIG      -0.68800
 12 H12        20.2773    2.2819  -53.9665 H      1 LIG       0.21400
 13 H13        20.0176    2.0033  -56.4027 H      1 LIG       0.20000
 14 H14        23.7285   -0.0277  -56.5143 H      1 LIG       0.32600
@<TRIPOS>BOND
  1       1       2 1
  2       2       3 1
  3       2       4 1
  4       2       5 1
  5       5       6 ar
  6       5      11 ar
  7       6       7 ar
  8       7       8 ar
  9       8       9 2
 10       8      10 ar
 11      10      11 ar
 12       6      12 1
 13       7      13 1
 14      10      14 1
@<TRIPOS>ALT_TYPE
CGenFF_4.0_ALT_TYPE_SET
CGenFF_4.0 1 FGA3 2 CG302 3 FGA3 4 FGA3 5 CG2R62 6 CG2R62 7 CG2R62 8 CG2R63 9 OG2D4 10 NG2R61 11 NG2R62 12 HGR62 13 HGR62 14 HGP1

1 个答案:

答案 0 :(得分:0)

要获得内存有效的文件行读取效果(例如,用\n或特定于操作系统的行结尾进行拆分),您可以使用

with open(sys.argv[1], "r") as f, open(sys.argv[2], 'w') as out:
    for i in f:
        ...

,但是您需要除以'\n@<TRIPOS>MOLECULE',所以我建议创建自己的生成器(具有yield的函数)以生成MOLECULE块,仅将1个块加载到内存中(延迟读取大文件) ,而不是使用贪婪的read()

def mol_reader(file_stream):
    chunk = []
    for line in file_stream:
        line = line.strip()
        if line == "@<TRIPOS>MOLECULE":
            if chunk:
                yield chunk
            chunk = []
        else:
            chunk.append(line)
    yield chunk


with open(sys.argv[1], "r") as f, open(sys.argv[2], 'w') as out:
    for mol_file in mol_reader(f):
        ...

例如https://repl.it/@PeterAprillion/chunk-iterator