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、子进程、管道和选择的主要内容,如果未能解决你的问题,请参考以下文章

带有管道和大文件的 Python 子进程

Python子进程:如何三次使用管道? [复制]

在 Windows 上使用 bq load 和 python 子进程分隔的加载管道

如何使用python子进程调用在命令中使用管道[重复]

带有管道的子进程调用[重复]

Linux中Python子进程之间管道的困难