问题
How do I make Popen use a fifo named pipe as stdin?
import subprocess
import os
import time
FNAME = 'myfifo'
os.mkfifo(FNAME, mode=0o777)
f = os.open(FNAME, os.O_RDONLY)
process = subprocess.Popen(
'wait2.sh',
shell=True,
stdout=subprocess.PIPE,
stdin=f,
stderr=subprocess.PIPE,
universal_newlines=True,
)
while process.poll() is None:
time.sleep(1)
print("process.stdin", process.stdin)
If I run this script and in a terminal window
echo "Something" > myfifo
The process exits with process.stdin None
. It seems its not getting the stdin from the fifo.
回答1:
According to the documentation, the Popen.stdin
is only not None
if the argument for that field was PIPE
, which is not the case in your code.
This code works fine for me, it prints "Line 1" and "Line 2" (from the child process) as expected
import subprocess
import os
import time
FNAME = 'myfifo'
os.mkfifo(FNAME, mode=0o777)
# Open read end of pipe. Open this in non-blocking mode since otherwise it
# may block until another process/threads opens the pipe for writing.
stdin = os.open(FNAME, os.O_RDONLY | os.O_NONBLOCK)
# Open the write end of pipe.
tochild = os.open(FNAME, os.O_WRONLY)
print('Pipe open (%d, %d)' % (stdin, tochild))
process = subprocess.Popen(
['/usr/bin/cat'],
shell=True,
stdout=None,
stdin=stdin,
stderr=None,
universal_newlines=True,
)
print('child started: %s (%s)' % (str(process), str(process.stdin)))
# Close read end of pipe since it is not used in the parent process.
os.close(stdin)
# Write to child then close the write end to indicate to the child that
# the input is complete.
print('writing to child ...')
os.write(tochild, bytes('Line 1\n', 'utf-8'))
os.write(tochild, bytes('Line 2\n', 'utf-8'))
print('data written')
os.close(tochild)
# Wait for child to complete.
process.wait()
os.unlink(FNAME)
来源:https://stackoverflow.com/questions/63132778/how-to-use-fifo-named-pipe-as-stdin-in-popen-python