目标是在Python中将一些数据(几个字节)从子进程传递到父进程(不能使用stdout和stderr)。下面是它的简化版本(实际代码在阻塞子流程之前从管道读取所有数据)
import os
import subprocess
import sys
CHILD_SCRIPT = r'''
import os
os.write({wfd}, b'Hello, World!')
'''
rfd, wfd = os.pipe()
if hasattr(os, 'set_inheritable'):
os.set_inheritable(wfd, True)
subprocess.check_call([sys.executable, '-c', CHILD_SCRIPT.format(wfd=wfd)])
print(os.read(rfd, 1024))
在Unix上,它可以在Python 2上工作,但不能在Python 3上工作,因为它在以下情况下失败:
Traceback (most recent call last):
File "<string>", line 3, in <module>
OSError: [Errno 9] Bad file descriptor
Traceback (most recent call last):
File "test_inherit_fd.py", line 13, in <module>
subprocess.check_call([sys.executable, '-c', CHILD_SCRIPT.format(wfd=wfd)])
File "/usr/lib/python3.8/subprocess.py", line 364, in check_call
raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['/bin/python3', '-c', "\nimport os\nos.write(5, b'Hello, World!')\n"]' returned non-zero exit status 1.
显然,失败与FD是否可继承无关。在Python3.2(默认情况下FD仍然是可继承的)上,它以同样的方式失败。还有什么原因造成这种差异?(EDIT:原因是,从Python3.2开始,2以上的FDs在默认情况下是关闭的。通过传递close_fds=False
可以解决这个问题)
在Windows上,它在Python 2和Python 3上失败
在所有平台上,在Python2和Python3上,从子级向父级传递数据(几个字节)的健壮而干净的方法是什么
我想你要找的是一个多处理队列
Python 3:https://docs.python.org/3/library/multiprocessing.html#exchanging-objects-between-processes
Python 2:https://docs.python.org/2/library/multiprocessing.html#exchanging-objects-between-processes
您也可以使用管道(来自同一个库),但它比队列慢得多:Python 3.4 multiprocessing Queue faster than Pipe, unexpected
编辑
“这是如何解决问题的?”
您正试图在子进程中执行代码,您需要一种将数据获取到父进程的方法。如果查看文档,您将看到如下代码片段:
在本例中
f
是将由子进程执行的代码。你可以在那里做任何你想做的事!制作一个1000行函数。创建一个类,实例化它,然后发疯。将名称从f
更改为有意义的名称。将该函数放在不同的文件中并导入它,然后使其执行从the ^{} documentation :
要使其工作,请将
close_fds=False
或pass_fds=[wfd]
作为参数添加到subprocess.check_call
。快速测试表明,如果您使用pass_fds
,则不再需要调用set_inheritable
,但如果您使用close_fds
,则情况并非如此相关问题 更多 >
编程相关推荐