Цель состоит в том, чтобы передать некоторые данные (несколько байтов) из дочернего процесса в родительский процесс в 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. В Python 3.2 (где FD по-прежнему наследовались по умолчанию) он не работает так же. Что еще вызывает разницу? (EDIT: причина в том, что, начиная с Python 3.2, FD выше 2 закрыты по умолчанию. Проблема может быть решена путем передачи close_fds=False
).
В Windows он не работает на Python 2 и Python 3.
Какой надежный и чистый способ передачи данных (несколько байтов) от дочернего к родительскому, который работает на Python 2 и Python 3 на всех платформах?