Python、子进程、管道和选择
Posted
技术标签:
【中文标题】Python、子进程、管道和选择【英文标题】:Python, subprocess, pipe and select 【发布时间】:2015-10-24 12:06:44 【问题描述】:我有一个 python 程序,我在其中不断读取通过 subprocess.Popen 启动并通过 subprocess.PIPE 连接的其他程序的输出
我面临的问题是它有时会丢失已启动程序的大部分输出。
例如,通过管道监控到 inotifywait
的 inotify 事件会丢失许多事件。
这是相关函数:
进程 = subprocess.Popen(["inotifywait", "-q", "-r", "-m", "--format", "%e:::::%w%f", srcroot], stdout=subprocess.PIPE, stderr=subprocess.PIPE) 轮询 = select.poll() polling.register(process.stdout) process.stdout.flush() 而真: process.stdout.flush() 如果 polling.poll(max_seconds*1000): line = process.stdout.readline() 如果长度(线)> 0: 打印行[:-1]执行命令inotifywait -q -r -m --format %e:::::%w%f /opt/fileserver/ > /tmp/log1
并移动一些文件(以生成inotify 事件)给出>8000 行文件。另一方面,使用我的./pscript.py > /tmp/log2
给出一个大约 5000 行的文件。
【问题讨论】:
尝试从 stderr 获取线路,然后打印,检查丢失的数据是否真的存在。 -print process.stderr.read()
不幸的是,上面的示例有些简化,因为我已经在检查 stderr。还是谢谢你。
【参考方案1】:
您在示例中完全忽略了 stderr。尝试像这样创建流程:
process = subprocess.Popen(["inotifywait", "-q", "-r", "-m",
"--format", "%e:::::%w%f", srcroot], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
此外,我会直接将 inotify 与它的一个 Python bindings 一起使用,而不是使用 inotifywait 生成一个进程。
【讨论】:
不幸的是,上面的示例有些简化,因为我已经在检查 stderr。此外,由于性能缓慢,我无法使用 pyinotify(我试过了,几千个文件都可以,但在我的情况下,它甚至无法创建足够数量的手表)......无论如何,谢谢。 您不必设置成千上万的手表。您为每个要监视的文件夹设置一个监视,应用程序将调用您的回调。如果您还需要监视子文件夹,则只需在创建监视时指定它即可。 在高层,是的。但在低级别,pyinotify 需要为任何不同的文件/目录建立一个监视。这个过程非常耗时,并且存在显着的可扩展性问题。纯 C 实现要快得多,主要是因为所有代码都已编译。以上是关于Python、子进程、管道和选择的主要内容,如果未能解决你的问题,请参考以下文章