等待文件的脚本在 while 循环中使用 100% CPU

Posted

技术标签:

【中文标题】等待文件的脚本在 while 循环中使用 100% CPU【英文标题】:Script waiting for files uses 100% CPU in while loop 【发布时间】:2015-01-14 03:07:04 【问题描述】:

我有一个脚本在等待循环中使用 100% 的单个内核。该脚本应处理出现在预设目录中的文件。因此,它会等到文件出现,然后处理它们。大致是这样的:

slept = 0
while True:
    if len(glob.glob(src_diretory+suffix)) > 0:
        slept=0
        # cast black magic spells on files ending in suffix, located in src_directory
    else:
        print("Slept "+str(slept)+" times.."
        slept+=1
        sleep.sleep(1)

在这种情况下,相当频繁的len(glob.glob(src_diretory+suffix)) 是否会导致如此高的 CPU 使用率?

【问题讨论】:

你确定else 真的有效吗?您是否从src_diretory+suffix 目录中删除/重命名文件? else 确实有效,用print("something") 进行了测试,我刚刚检查了sleep 甚至是1s 而不是0.1s。是的,如果找到文件,它们会被移动、处理然后删除。 【参考方案1】:

解决此类问题的第一个工具是profiler,它会详细告诉您时间花在了哪里。

您不需要测试长度是否大于零;如果列表有条目,则为真,否则为假。此外,您可能应该在阅读时使用您的条目。然而,这些只是表面上的变化,所以我最好的猜测是 glob 本身需要很长时间;可能有很多文件与同一目录中的模式不匹配?

我会建议一个稍微不同的结构:

while True:
    filenames = glob.glob(src_diretory+suffix)
    for filename in filenames:
        pass  # Process file here, including moving it away
    if not filenames:
        time.sleep(1)

理想情况下,您将使用操作系统端监视器来进行更改,例如 inotify、kqueue、FSEvents 或 ReadDirectoryChanges,而不是轮询。您可能想尝试执行此特定等待的程序,例如 incron 和 entr。

【讨论】:

【参考方案2】:

根据操作系统(*),您可以找到允许程序警告在目录中创建新文件而无需执行主动循环的低级函数。不幸的是,它是不可移植的,并且可能无法直接从 Python 中获得。

如果你正在构建一个高性能系统,你可以看看这个,否则,你应该使用一个简单的假脱机算法:

只要在目录中找到文件:处理它们 只要您没有文件 - 在迭代之前休眠一段时间(常用值在 0.1 到 2 秒之间)

(*) 至少存在于 Windows 和最近的 Linux 内核中

【讨论】:

【参考方案3】:

while 循环会尽量占用 mutch cpu,比较一下:

while True:
    pass

while True:
    time.sleep(0.001)

【讨论】:

感谢您的提示,但我无法在脚本运行的机器上对此进行测试。您的示例是 100% CPU 使用率的经典示例,我知道这一点,但我使用 sleep(0.1) 对于 CPU(四核)来说有点 long 所以我假设 CPU 使用结果来自len(glob.glob(src_diretory+suffix)) len(glob.glob(src_diretory+suffix)) > 0 我想相当快,而且大多数时候都是真的?

以上是关于等待文件的脚本在 while 循环中使用 100% CPU的主要内容,如果未能解决你的问题,请参考以下文章

Bash while 循环等待任务完成

在使用读取(bash)的while循环中禁用用户输入

Linux的shell脚本实战之while循环

如何在while循环期间运行“文件存在”函数(expect/tcl)作为条件?

While循环重置Bash脚本中的数字变量[重复]

inotifywait 未在 bash 脚本中执行 while 循环