【问题标题】:How to search specific lines in a file and write them to another file, using function in Python如何使用Python中的函数搜索文件中的特定行并将它们写入另一个文件
【发布时间】:2015-09-22 08:01:35
【问题描述】:

我的目标是构建一个日志解析器,它将复制我想要的关键字之间的选定行并将其写入文件。由于我必须在单个文件中的多个关键字之间进行搜索,因此我想编写一个函数并在我的脚本中多次使用它。

但是我无法通过以下脚本实现这一点并收到错误:

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'

【问题讨论】:

  • Poke 展示了如何修复您的功能。您不需要为此使用正则表达式:您可以使用if search1 in line:,这要快得多。此外,如果您想多次调用该函数并将所有结果保存到同一个输出文件,那么您需要以'a' 追加模式而不是'w' 写入模式打开文件。

标签: python parsing python-3.x text


【解决方案1】:
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

最后一点:文件句柄应始终从打开它们的同一级别关闭。因此,如果您在函数中打开文件句柄,那么 that 函数也应该关闭它。如果您在函数外部打开文件,则函数不应关闭它。关闭文件是打开者的责任,而其他情况下关闭文件可能会导致错误的行为,所以你不应该这样做(除非它被明确记录,例如函数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, …)

【讨论】:

  • 非常感谢....您的建议很有效。但是仍然很少有人问。 1. 当我使用没有函数的相同脚本时,“fi.close()”已经工作并且没有给出任何错误。 2. 我在函数内部以“with open(outfile, 'a') as fo:”的形式打开了 outfile,但是当我在脚本中使用不同的搜索字符串两次调用此函数时,它没有附加下一次搜索的结果。似乎第二次该功能根本不起作用。现在,当我从脚本中删除第一个函数调用时,另一个函数返回了所需的结果
  • (1) 只有在变量名之前不同的情况下才有效。如果fireadlines() 的结果,那么它就无法工作。 (2) 这很可能是因为您正在关闭函数内部的infile。因此,当您第二次运行该函数时,该文件已关闭,因此您无法从中读取。您应该在函数内部也打开文件,或者不要在内部关闭它。文件句柄应始终由打开它们的同一实例关闭。请注意,如果您为多个函数调用保持打开状态,您需要从头开始重新读取。
  • 最初我没有关闭函数内部的文件,但它仍然没有附加结果。现在,当我指定打开此文件并稍后在函数中关闭时,它不起作用--------------------------------- --------------------- filein = open (infile , "r") fi = filein.readlines() 在函数的最后一个 infile.close()
  • 你能用你当前的代码打开一个新问题吗?跟随你正在做的事情有点困难。另请参阅我添加到答案中的最后一部分,也许这会有所帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-13
  • 2012-10-25
  • 2017-04-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多