如果从sys.stdin
开始为readline()
,则将其其余部分传递给子进程似乎不起作用.
import subprocess
import sys
header = sys.stdin.buffer.readline()
print(header)
subprocess.run(['nl'], check=True)
(我使用sys.stdin.buffer
来避免任何编码问题;该句柄返回原始字节.)
这会运行,但我没有从子进程中获得任何输出;
bash$ printf '%s\n' foo bar baz | python demo1.py
b'foo\n'
如果我go 掉readline
个ETC,子流程将读取标准输入并生成我预期的输出.
bash$ printf '%s\n' foo bar baz |
> python -c 'import subprocess; subprocess.run(["nl"], check=True)'
1 foo
2 bar
3 baz
当我开始阅读标准输入的其余部分时,是不是Python在缓冲它,或者这里发生了什么?用python -u
运行并不能解决这个问题(实际上,它的文档只提到它改变了stdout
和stderr
的行为).但如果我传递更多的数据,我确实会得到一些数据:
bash$ wc -l /etc/services
13921 /etc/services
bash$ python demo1.py </etc/services | head -n 3
1 27/tcp # NSW User System FE
2 # Robert Thomas <BThomas@F.BBN.COM>
3 # 28/tcp Unassigned
(... traceback from broken pipe elided ...)
bash$ fgrep -n 'NSW User System FE' /etc/services
91:nsw-fe 27/udp # NSW User System FE
92:nsw-fe 27/tcp # NSW User System FE
bash$ sed -n '1,/NSW User System FE/p' /etc/services | wc
91 449 4082
(因此,看起来它从开始就占用了4096个字节.)
不过,我有没有办法避免这种行为呢?我只想从头开始读一行,然后将其余内容传递给子过程.
在循环中重复拨打sys.stdin.buffer.readline(-1)
不会有任何帮助.
这实际上是Read line from shell pipe, pass to exec, and keep to variable的后续问题,但我想把重点放在这个问题中令我惊讶的方面.