John Nagle wrote: > I have working code from Python 2 which uses "pickle" > to talk to a subprocess via stdin/stdio. I'm trying to > make that work in Python 3. > > First, the subprocess Python is invoked with the "-d' option, > so stdin and stdio are supposed to be unbuffered binary streams. > That was enough in Python 2, but it's not enough in Python 3. > > The subprocess and its connections are set up with > > proc = subprocess.Popen(launchargs,stdin=subprocess.PIPE, > stdout=subprocess.PIPE, env=env) > > ... > self.reader = pickle.Unpickler(self.proc.stdout) > self.writer = pickle.Pickler(self.proc.stdin, 2) > > after which I get > > result = self.reader.load() > TypeError: 'str' does not support the buffer interface > > That's as far as traceback goes, so I assume this is > disappearing into C code. > > OK, I know I need a byte stream. I tried > > self.reader = pickle.Unpickler(self.proc.stdout.buffer) > self.writer = pickle.Pickler(self.proc.stdin.buffer, 2) > > That's not allowed. The "stdin" and "stdout" that are > fields of "proc" do not have "buffer". So I can't do that > in the parent process. In the child, though, where > stdin and stdout come from "sys", "sys.stdin.buffer" is valid. > That fixes the ""str" does not support the buffer interface > error." But now I get the pickle error "Ran out of input" > on the process child side. Probably because there's a > str/bytes incompatibility somewhere. > > So how do I get clean binary byte streams between parent > and child process?
I don't know what you have to do to rule out deadlocks when you use pipes for both stdin and stdout, but binary streams are the default for subprocess. Can you provide a complete example? Anyway, here is a demo for two-way communication using the communicate() method: $ cat parent.py import pickle import subprocess data = (5, 4.3, "üblich ähnlich nötig") p = subprocess.Popen( ["python3", "child.py"], stdin=subprocess.PIPE, stdout=subprocess.PIPE) result = p.communicate(pickle.dumps(data, protocol=2))[0] print(pickle.loads(result)) $ cat child.py import sys import pickle a, b, c = pickle.load(sys.stdin.buffer) pickle.dump((a, b, c.upper()), sys.stdout.buffer) $ python3 parent.py (5, 4.3, 'ÜBLICH ÄHNLICH NÖTIG') This is likely not what you want because here everything is buffered so that continuous interaction is not possible. -- https://mail.python.org/mailman/listinfo/python-list