如何使用Python中的函数搜索文件中的特定行并将其写入另一个文件

时间:2015-09-22 08:01:36

标签: python parsing python-3.x text

我的目标是构建一个日志解析器,它将复制我想要的关键字和写入文件。因为我必须在单个文件中搜索多个关键字,所以我想在我的脚本中编写一个函数并多次使用它。

但是我无法通过以下脚本实现此操作并收到错误:

import re

def myfunc (infile ,outfile, search1 , search2):

    fi =  infile.readlines()
    fo =  open(outfile, 'w')

    write1 = False
    for line in fi:
     if re.findall('search1' , str(line)):
        write1 = True
     elif re.findall('search2', str(line)):
        write1 = False
     elif write1:
        fo.write(line)

    fo.close()
    fi.close()

    return;

text_file = open(input("name of inputfile : "))
resultfile =  input("name of outputfile : ")

search1 = "teen"
search2 = "eight"
myfunc (text_file , resultfile , search1 , search2)

我收到以下错误:

Traceback (most recent call last):
  File "C:/Users/zoro/PycharmProjects/text-parsing/write selected test 2 sets.py", line 38, in <module>
    myfunc (text_file , resultfile , search1 , search2)
  File "C:/Users/zoro/PycharmProjects/text-parsing/write selected test 2 sets.py", line 28, in myfunc
    fi.close()
AttributeError: 'list' object has no attribute 'close'

1 个答案:

答案 0 :(得分:2)

fi = infile.readlines()

这会使fi成为文件infile中的行列表。因此,当您稍后致电fi.close()时,您正试图关闭列表,这当然不起作用。

相反,您需要关闭该文件,即infile

infile.close()

一般来说,以某种方式更改变量名称是个好主意,因此它们包含的内容很明显。 infile是您读取的文件对象,所以没关系。 outfile是您要写入的文件的文件名,因此您应该将其命名为outFileName或其他内容。 fiinfile中的行列表,因此您应该将其称为inFileLines

您还应该避免手动关闭文件对象;相反,使用with语句确保它们自动关闭:

with open(outfile, 'w') as fo:
    fo.write('stuff')
    # no need to manually close it

最后,您的代码还有另一个问题:re.findall('search1' , str(line))这将在该行中搜索字符串'search1';它不会尊重传递给函数的值并存储在search1(和search2)变量中。因此,您需要删除那里的引号:re.findall(search1, line)(您也不需要将该行转换为字符串)。

另外,如果仅评估其真值,则使用re.findall()并不是最好的方法。相反,使用仅返回第一个结果的re.search(因此对于非常长的行,如果已经找到结果,则不会继续搜索)。如果search1search2不包含实际正则表达式,而只包含您想要在该行中找到的字符串,那么您还应该只使用in运算符:

if search1 in line:
    write1 = True

最后一点:文件句柄应始终从打开它们的同一级别关闭。因此,如果您在函数内打开文件句柄,那么 函数也应该关闭它。如果在函数外部打开文件,则该函数不应关闭它。关闭文件是开启者的责任,而关闭文件的其他实例可能会导致错误的行为,因此您不应该这样做(除非明确记录,例如函数doSomethingAndClose可能会关闭文件)。

使用with语句通常可以避免这种情况,因为您从未手动调用file.close()with语句已确保文件已正确关闭。

如果您想多次使用文件,则必须seek to the beginning才能再次阅读该文件。在您的情况下,由于您使用infile.readlines()将整个文件读入内存,因此最好只从文件中读取一行行,然后将其重用于多个函数调用:

text_file = input("name of inputfile : ")
with open(text_file) as infile:
    fi = infile.readlines() # read the lines *once*

    myfunc(fi, …)
    myfunc(fi, …)
    myfunc(fi, …)