在Python中循环搜索字符串直至找到目标字符串

3 投票
3 回答
9776 浏览
提问于 2025-04-16 10:59

我原以为这件事会很简单,但经过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 个回答

1

正如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)
1

你程序的问题在于,你在读取输入文件的同时还在写入输出文件。所以如果你找到了一次你想要的输入,程序就会进入一个无限循环,因为它会一直读取最后一行,然后把它再写回到输出文件中,而这个输出文件其实就是输入文件,然后就这样不断重复。

我建议你可以试试这样的程序:

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
4

不错的代码,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真是太棒了。

撰写回答