Reputation: 6405
I want to spawn a child process in Python, whose standard streams are used for other purposes and I can't touch them, and I want to have a dedicated pipe for my own purposes, independent of standard streams.
In Python version 2, the following works:
foobar.py
:
#!/usr/bin/python
from os import pipe, environ, read
import subprocess
output, input = pipe()
new_environ = environ.copy()
new_environ["PIPE_INPUT"] = str(input)
subprocess.Popen(['./a.out'], env=new_environ)
print(read(output, 6))
and a.out
is compiled from foobar.c
:
#include <unistd.h>
#include <stdlib.h>
void main() {
write(atoi(getenv("PIPE_INPUT")), "foobar", 6);
}
This works, ./foobar.py
prints foobar
.
But, with the shebang line
#!/usr/bin/python3
it does not work. Of course, this is because, according to the docs, in Python 3 the descriptors are not inheritable.
Well, then how do I do this in Python 3, and also so that the same code works for Python 2. I cannot have different code for different Pythons, has to be portable code for Python 2 and 3.
Upvotes: 2
Views: 292
Reputation: 10969
To make the input
descriptor inheritable if necessary, use
import os
try:
os.set_inheritable(input, True)
except AttributeError:
# This is Python 3.3 or older -> Nothing to do
pass
The Popen
call must then be modified to
subprocess.Popen(['./a.out'], env=new_environ, close_fds=False)
which works on Python 2 and Python 3.
Upvotes: 1