gpt4 book ai didi

python - Bash管道到python

转载 作者:IT王子 更新时间:2023-10-29 00:40:35 24 4
gpt4 key购买 nike

我需要通过管道实时吸收 bash 命令的输出。例如

for i in $(seq 1 4); do echo $i; sleep 1; done | ./script.py

script.py 有这个

for line in sys.stdin.readlines():
print line

我希望序列在可用时打印出来,但 python 脚本正在等待 bash 脚本结束,然后再继续。

我看了this相关答案,但这并没有解决我的问题。我该如何在 Python 中实现这一点?

最佳答案

第一个问题是readlines将所有行读入列表。在所有行都出现之前,它不能这样做,直到 stdin 达到 EOF。

但是您实际上不需要行的列表,只需要一些可迭代的行。而像 sys.stdin 这样的文件,已经是这样的可迭代对象了。而且它是一个惰性的,一旦它们可用就一次生成一行,而不是等待一次生成它们。

所以:

for line in sys.stdin:
print line

每当您发现自己需要readlines 时,问问自己是否真的需要它。答案总是是否定的。 (好吧,除非你想用参数调用它,或者在一些有缺陷的不完全像文件的对象上调用它。)参见 Readlines Considered Silly了解更多。


但与此同时,还有一个第二个问题。并不是说 Python 正在缓冲它的 stdin,或者另一个进程正在缓冲它的 stdout,而是文件对象迭代器本身正在做内部缓冲,这可能(取决于在你的平台上——但在大多数 POSIX 平台上,它通常会)阻止你到达第一行直到 EOF,或者至少直到很多行被读取。

这是 Python 2.x 的一个已知问题,已在 3.x 中修复,* 但这对您没有帮助,除非您愿意升级。

该解决方案在命令行和环境文档以及大多数系统的联机帮助页中都有提到,但隐藏在 -u flag documentation 的中间。 :

Note that there is internal buffering in xreadlines(), readlines() and file-object iterators ("for line in sys.stdin") which is not influenced by this option. To work around this, you will want to use "sys.stdin.readline()" inside a "while 1:" loop.

换句话说:

while True:
line = sys.stdin.readline()
if not line:
break
print line

或者:

for line in iter(sys.stdin.readline, ''):
print line

对于不同的问题,在 this answer , Alex Martelli 指出,您始终可以忽略 sys.stdin 并重新 fdopen 文件描述符。这意味着您获得了 POSIX fd 的包装器而不是 C stdio 句柄。但这对于这个问题既不必要也不充分,因为问题不在于 C stdio 缓冲,而在于 file.__iter__ 缓冲与其交互的方式。


* Python 3.x 不再使用 C stdio 库的缓冲;它自己做所有事情,在 io 中的类型中模块,这意味着迭代器可以共享文件对象本身正在使用的相同缓冲区。虽然 io 在 2.x 上也可用,但它不是您为 open 或 stdio 文件句柄获得的默认内容,这就是它无济于事的原因在这里。

关于python - Bash管道到python,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30043857/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com