【发布时间】:2015-04-16 10:25:39
【问题描述】:
我正在尝试在 Python 中执行一些简单的 IPC,如下所示:一个 Python 进程使用subprocess 启动另一个进程。子进程将一些数据发送到管道中,父进程接收它。
这是我当前的实现:
# parent.py
import pickle
import os
import subprocess
import sys
read_fd, write_fd = os.pipe()
if hasattr(os, 'set_inheritable'):
os.set_inheritable(write_fd, True)
child = subprocess.Popen((sys.executable, 'child.py', str(write_fd)), close_fds=False)
try:
with os.fdopen(read_fd, 'rb') as reader:
data = pickle.load(reader)
finally:
child.wait()
assert data == 'This is the data.'
# child.py
import pickle
import os
import sys
with os.fdopen(int(sys.argv[1]), 'wb') as writer:
pickle.dump('This is the data.', writer)
在 Unix 上这按预期工作,但如果我在 Windows 上运行此代码,我会收到以下错误,之后程序会挂起直到被中断:
Traceback (most recent call last):
File "child.py", line 4, in <module>
with os.fdopen(int(sys.argv[1]), 'wb') as writer:
File "C:\Python34\lib\os.py", line 978, in fdopen
return io.open(fd, *args, **kwargs)
OSError: [Errno 9] Bad file descriptor
我怀疑问题在于子进程没有继承write_fd 文件描述符。我该如何解决这个问题?
代码需要与 Python 2.7、3.2 以及所有后续版本兼容。这意味着解决方案不能依赖于PEP 446 中指定的文件描述符继承的更改是否存在。如上所述,它还需要在 Unix 和 Windows 上运行。
(回答几个明显的问题:我不使用multiprocessing 的原因是,在我的实际非简化代码中,这两个 Python 程序是具有不同设置模块的 Django 项目的一部分。这个意味着它们不能共享任何全局状态。此外,子进程的标准流正被用于其他目的,不能用于此目的。)
更新: 设置 close_fds 参数后,代码现在可以在 Unix 上的所有 Python 版本中运行。但是,它在 Windows 上仍然失败。
【问题讨论】:
-
这并不能直接回答您的问题,但execnet 会这样做。
-
我更喜欢一种不会引入额外依赖的解决方案,特别是因为我已经拥有了大部分。但如果我别无选择,我可能会选择这个。
-
也许您可以深入研究他们的实现,看看他们是如何做到的。它适用于 Linux 和 Windows。
标签: python pipe subprocess ipc