在Python中循环搜索字符串直至找到目标字符串
我原以为这件事会很简单,但经过3个小时的搜索和反复尝试,发现并没有那么容易。
我想做的就是不断搜索一个字符串,直到找到它为止。我在一个日志文件中查找一个字符串,这个字符串会在某个条件出现时出现,比如当日志中出现字符串 "function test 1"
时,我需要找到它,然后执行另一个函数。
找到这个字符串没问题,问题是我想要不断循环,直到找到它。
这个代码能完美找到:
for line in open(WebPath + SmokeTest): #these are variables I use to construct the path
if 'readfalseloop2' in line:
print True
f = open(WebPath + SmokeTest,'a')
f.write('<font color= "#347C2C">readfalseloop2</font><br />')
f.close()
break
else:
print False
我想要一直执行这个代码,直到找到那个词。理想情况下,我希望把这个嵌入到多个函数中,而不是在这个时候单独定义一个函数。
我尝试过各种循环的方法,但都没有成功。是的,我看过Python的文档,也在这个网站上搜索过,还查阅了ubuntu论坛。
3 个回答
正如vy32提到的,边读边写同一个文件可能会很麻烦(具体表现会因操作系统而异)。
另外,不太清楚你正在读取的文件是否被其他程序实时更新。我会假设是这样,因为如果只是简单地逐行读取就能解决问题。
在读取一个实时更新的文件时,标准的迭代器并不是你想要的,因为它一旦遇到文件结束标记就会停止。要监控一个实时文件,你需要定期检查它是否有新数据,或者设置一些操作系统特定的通知机制,让你知道何时有新数据可用。
关于这个问题,这里有一些不错的答案: 如何监控文件的变化?
不过,写回同一个文件仍然可能会出现问题,特别是当其他程序也在写这个文件时(即使你能让多个程序同时访问,也很难让监控程序忽略自己的写入,而不冒着错过被监控程序写入的风险)。
下面是一个使用文件行迭代器和collections.deque的例子,可以在享受行迭代器所有I/O优化的同时,记住上下文信息:
context = deque(maxlen=10) # Remember most recent 10 lines
for line in f:
# Process the current line
context.append(line)
你程序的问题在于,你在读取输入文件的同时还在写入输出文件。所以如果你找到了一次你想要的输入,程序就会进入一个无限循环,因为它会一直读取最后一行,然后把它再写回到输出文件中,而这个输出文件其实就是输入文件,然后就这样不断重复。
我建议你可以试试这样的程序:
import re
r = re.compile("readflaseloop2")
in_fn = WebPath + inputName
outf = open(in_fn + ".log","a")
count = 0
for line in open(in_fn):
m = r.search(line)
if m:
if count==0:
print True
outf.write("<font color='#347C2C'>%s</font><br>\n" % m.group(0))
outf.flush()
count += 1
if count==0:
print False
不错的代码,Andrew。我之前不知道有for/else这种用法。
不过,为了让机器的处理过程更顺畅,可以避免重复打开和关闭文件,最好是降低检查的频率,我觉得这样更好。
from time import sleep
with open(WebPath + SmokeTest,'a+') as f:
while True:
if 'readfalseloop2' in f.read():
f.seek(0,1)
f.write('\n<font color= "#347C2C">readfalseloop2</font><br />')
print True
break
print '~',
f.seek(0,0)
sleep(2)
这段代码是有效的,我测试过了。但前提是文件的修改是通过其他程序进行的。当我尝试手动插入
<font color= "#347C2C">readfalseloop2</font><br />
内容时,Windows拒绝关闭正在修改的文件。
.
在执行f.read()之后,文件的指针f必须重新激活,这样才能在文件内容的末尾写入新的
<font color= "#347C2C">readfalseloop2</font><br />
内容。
我不知道这个重新激活具体是怎么回事。我只知道如果不执行f.seek(0,1)这条指令,程序就无法从“读取”模式切换到“写入”模式。
f.seek(0,1)的意思是“从当前位置移动0个字符”;因为指针已经在文件末尾,所以再给其他指令也没用,反正写的时候指针会回到文件末尾:这就是'a'模式的特点。所以,即使通过f.seek(0,0)把指针重新放到文件开头,写入的内容还是会在文件末尾。
;
如果测试if 'readfalseloop2' in f.read()的结果是False,那么指针必须通过f.seek(0,0)移动到文件的最开始,以便重新读取整个文件的内容。
.
注意:我不知道如果文件是用utf-8编码写的会发生什么,因为在utf-8中,字符的字节长度是不一样的,取决于具体的字符。在我看来,即使是utf-8也应该能正常工作。
.
编辑
我找到了一个更清晰、更简短的代码:
from time import sleep
with open(WebPath + SmokeTest,'r+') as f:
while not 'readfalseloop2' in f.read():
print '~',
f.seek(0,0)
sleep(2)
f.seek(0,1)
f.write('\n<font color= "#347C2C">readfalseloop2</font><br />')
print 'True'
或者
from time import sleep
with open(WebPath + SmokeTest,'r') as f, open(WebPath + SmokeTest,'a') as g:
while not 'readfalseloop2' in f.read():
print '~',
f.seek(0,0)
sleep(2)
g.write('\n<font color= "#347C2C">readfalseloop2</font><br />')
print 'True'
8行代码。Python真是太棒了。