【问题标题】:Loop a string search until a string is found python循环字符串搜索,直到找到一个字符串python
【发布时间】:2011-06-18 23:31:52
【问题描述】:

我认为这很容易,经过 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

我想执行这个直到找到单词。理想情况下,我想将它嵌入到多个函数中,此时我不想要单独的 def。

我在任何循环结构上都没有成功,是的,我查看了 python 文档,搜索了这个站点并 ubuntu forum.

【问题讨论】:

  • 循环对我来说看起来不错。究竟会发生什么?如果你想把它嵌入到多个函数中,我会把它放到它自己的函数中。还是您的意思是您以某种方式监视日志文件,并且一旦文件更改,您的代码必须检测此更改并测试它是否包含某个字符串?
  • 是的,这正是我想要做的。
  • 我还没有在网上找到一个工作示例,说明如何在不使用我在 Sikuli 被阻止的第 3 方库的情况下做到这一点

标签: python string search file-io


【解决方案1】:

很好的代码安德鲁。我没有被告知存在 for/else 可能性。

但是为了缓和机器进程的活动,可以避免重复打开和关闭文件,最好是冷却IMO验证的频率

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 太棒了

【讨论】:

  • 这在文件没有被打开和关闭的意义上肯定更好,但是如果文件很大,一次读取整个文件可能是一个问题,仍然是 +1。
  • @Andrew 是的,确实如此。处理一个大文件仍然会导致同样烦人的特定问题。如果一次性读完,对内存来说很重;如果一次读一行,它可能会很长。我没有通用的解决方案。在本例中,user577229 想要处理一个日志文件,该文件可能不会太大。
  • 名字加单引号会导致代码失败,jython不知道怎么处理。我在制作这些 sn-ps 功能方面没有任何成功
  • java.nio.channels.NonReadableChannelException: with open(WebPath + SmokeTest,'a+') as f: while True: if "test" in f.read(): f.write('\ nreadfalseloop2
    ') f.seek(0,1) print True #break print '~', f.seek(0,0) sleep(2)
  • 我试图做的是读取一个日志文件,直到出现一个特定的值。一旦出现,我正在使用的自动化将知道它们与另一台机器同步,并将恢复脚本执行。这可能吗?日志文件非常小,只有 1 到 15 kmax。
【解决方案2】:

您的程序的问题是正在读取输入文件并写入输出文件。因此,如果您找到请求输入的单个实例,您的程序将进入无限循环,因为它将继续读取最后一行,将其重新附加到输出文件,即输入文件,然后重复。

我建议这样的程序:

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

【讨论】:

  • 为什么用 r.search(line) 而不是 r.search(content_of_file) ?
  • 因为我想查看匹配的每一行。使用 r.search(content_of_file) 您需要将已处理的输出与尚未处理的输出拼接起来,如果您想获得下一个匹配项,这将显着增加内存利用率。但显然这不是创作者想要的。
【解决方案3】:

正如 vy32 所指出的,写入您当前正在读取的同一文件可能会很棘手(具体行为取决于操作系统)。

您正在阅读的文件是否正在由另一个进程实时更新也不完全清楚。我将假设是这种情况,否则简单的行迭代就可以解决问题。

读取实时文件时,标准迭代器并不是您真正想要的,因为它会在遇到 EOF 标记时立即终止。要监视实时文件,您需要定期轮询它以获取新数据,或者设置一种特定于操作系统的通知机制,让您知道何时有新数据可用。

这个问题有一些很好的答案: How do I watch a file for changes?

写回同一个文件仍然是一个潜在的问题,特别是如果另一个进程打开它以进行写入(即使你获得并发访问工作,让监控程序忽略也会很棘手它自己的写入,而不会有丢失被监控应用程序写入的风险)。

使用带有 collections.deque 的文件行迭代器来记住上下文信息同时仍然受益于行迭代器内置的所有 I/O 优化的示例:

context = deque(maxlen=10) # Remember most recent 10 lines
for line in f:
    # Process the current line
    context.append(line)

【讨论】:

  • 很好的信息但是我正在寻找特定的内容,所以线路选项不能满足我的需要。
  • 如果您需要保留一些上下文,您可以相当轻松地使用设置了“maxlen”的双端队列来记住少量先前的行。这为您提供了文件迭代器内置缓存的好处,而不会丢失您需要的上下文。
猜你喜欢
  • 1970-01-01
  • 2014-06-28
  • 2023-02-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-10
  • 2020-02-02
  • 2015-04-30
相关资源
最近更新 更多