Python 基于列表查找字符串的有效方法

Python 基于列表查找字符串的有效方法,python,python-2.7,Python,Python 2.7,我是脚本编写新手,已经阅读Python大约6周了。如果找到srchstring中定义的某个关键字,则以下命令用于读取日志文件并发送警报。它按预期工作,不会像预期的那样对以前找到的字符串发出警报。但是,应用程序正在主动写入其处理的文件,并且脚本在500mb左右的文件上速度太慢。在200mb以下工作正常,即在20秒内。 有人能提出一种更有效的方法,根据预定义列表在文件中搜索字符串吗 import os srchstring = ["Shutdown", "Disconnecting", "Stopp

我是脚本编写新手,已经阅读Python大约6周了。如果找到
srchstring
中定义的某个关键字,则以下命令用于读取日志文件并发送警报。它按预期工作,不会像预期的那样对以前找到的字符串发出警报。但是,应用程序正在主动写入其处理的文件,并且脚本在500mb左右的文件上速度太慢。在200mb以下工作正常,即在20秒内。 有人能提出一种更有效的方法,根据预定义列表在文件中搜索字符串吗

import os
srchstring = ["Shutdown", "Disconnecting", "Stopping Event Thread"]

 if os.path.isfile(r"\\server\\share\\logfile.txt"):
 with open(r"\\server\\share\\logfile.txt","r") as F:
    for line in F:
        for st in srchstring:
            if st in line:
                print line,
                #do some slicing of string to get dd/mm/yy hh:mm:ss:ms
                # then create a marker file called file_dd/mm/yy hh:mm:ss:ms 
                if os.path.isfile("file_dd/mm/yy hh:mm:ss:ms"): # check if a file already exists named file_dd/mm/yy hh:mm:ss:ms
                    print "string previously found- ignoring, continuing search"  # marker file exists
                else:
                    open("file_dd/mm/yy hh:mm:ss:ms", 'a') # create file_dd/mm/yy hh:mm:ss:ms
                    print "error string found--creating marker file sending email alert"  # no marker file, create it then send email

 else:
    print "file not exist"

这里我假设您使用Linux。如果不这样做,请在Windows上安装MinGW,下面的解决方案也将适用

把最难的部分留给最有效的工具。在转到python脚本之前过滤数据。使用
grep
命令获取包含
“关机”
“断开连接”
“停止事件线程”

并将行重定向到脚本

grep 'Shutdown\|Disconnecting\|"Stopping Event Thread"' /server/share/logfile.txt | python log.py
编辑:Windows解决方案。您可以创建一个
.bat
文件以使其可执行

findstr /c:"Shutdown" /c:"Disconnecting" /c:"Stopping Event Thread" \server\share\logfile.txt | python log.py
在'log.py'中,从标准输入读取。这是一个类似文件的对象,因此在这里没有困难:

import sys

for line in sys.stdin:
    print line,
    # do some slicing of string to get dd/mm/yy hh:mm:ss:ms
    # then create a marker file called file_dd/mm/yy hh:mm:ss:ms 
    # and so on

此解决方案将减少脚本所需的工作量。由于Python不是一种快速语言,它可能会加快任务的速度。我怀疑它完全可以在
bash
中重写,而且速度会更快(20多年的C程序优化不是一件容易与之竞争的事情),但我对bash的了解还不够。

将搜索表达式重构为预编译正则表达式可以避免(显式)最内部的循环

import os, re
regex = re.compile(r'Shutdown|Disconnecting|Stopping Event Thread')

if os.path.isfile(r"\\server\\share\\logfile.txt"):
    #Indentation fixed as per comment
    with open(r"\\server\\share\\logfile.txt","r") as F:
       for line in F:
            if regex.search(line):
                # ...

这个代码运行吗?什么是
F
?我假设是您正在读取的文件,但代码没有反映这一点。此外,当您打开一个文件进行写入时,并不关闭它。pythonic写入文件的方法是使用context:
和open('filename')作为f:…
。对于您的问题,我会尝试使用
set
而不是
列表来处理
srchstring
。然后,对于文件中的每一行,对行中的单词进行
设置(例如
linset=set(line.split(“”))
)和使用集交点(请参阅)。如果它不是空的,那么就有一个匹配项。我猜这可能会加快搜索速度。你知道开销来自于搜索中的
?可能是您正在将整个文件读入内存,但没有显示该代码。
F
来自何方?抱歉,我在编辑文章以获得正确格式时漏掉了一行。我现在已经更新了。我在某个地方读到,嵌套的“如果”可能不是最好的方法,但我找不到建议这样做的帖子。这就是为什么我认为IF可能是瓶颈。我使用了“with open..”,因为我知道这可以处理文件的关闭(在原始帖子中意外删除)。我将试验linset=set(line.split(“”))建议。您的代码仍然存在缩进错误。我猜带有open
应该缩进,并且在
else
之前,它下面的所有内容都应该相应地重新缩进,但是由于不鼓励编辑代码,我只在这里指出这一点。换句话说,我们可能猜得出你的意思,但是发布与本地缩进不同的Python代码是非常糟糕的形式。@toon无论如何,这种方法仍然有效
grep
被多次移植到windows(我建议通过安装MinGW包来获得),windows有自己的工具
find
findstr
。如果我找到合适的,我会很快用WindowsAnalog更新这篇文章。你为什么说Python不快?对于脚本语言,它经过了合理的优化,可以一次读取一行输入。不过,剩下的Python脚本相当愚蠢。为什么这么愚蠢?查找部分并没有那么难,但是重新读取文件并忽略以前找到的字符串对于用户来说可能很棘手beginner@tripleeepython脚本可能比在文本流中搜索字符串的专用工具慢,这就是我想说的。@Vovanrock2002您的方法是目前为止最快的,因此,这是正确答案。所有反馈都是一次很好的学习经历。你必须从某个地方开始,对吗?:)使用regex提高了搜索速度,我估计搜索速度超过了10倍——谢谢,通常我可能有点匆忙,因为在应用程序写入文件时运行它只会返回稍微快一点的结果。当文件没有被写入正则表达式时,速度更快,所以谢谢。
import os, re
regex = re.compile(r'Shutdown|Disconnecting|Stopping Event Thread')

if os.path.isfile(r"\\server\\share\\logfile.txt"):
    #Indentation fixed as per comment
    with open(r"\\server\\share\\logfile.txt","r") as F:
       for line in F:
            if regex.search(line):
                # ...