为什么 stdbuf 对 Python 没有影响?
Why stdbuf has no effect on Python?
在 Python 中给出以下程序:
import sys
print("input")
while True:
pass
和 C 中的等价物:
#include <stdio.h>
int main() {
printf("input\n");
while(1);
return 0;
}
当我使用 cat
对程序进行管道传输时,默认情况下输出是缓冲的(而不是行缓冲的)。结果,我没有输出:
% python3 ./a.py | cat
(empty)
% ./a.out | cat
(empty)
我可以使用 stdbuf
切换回行缓冲:
% stdbuf -oL ./a.out | cat
input
但这不适用于 Python:
% stdbuf -oL python3 a.py | cat
(empty)
知道为什么吗?我知道 python3 -u
的存在,但我想要行缓冲,而不是 "no buffering" 并且我希望此命令行也适用于其他语言。命令 unbuffer
似乎也有效,但我想了解为什么 stdbuf
在这里不起作用。
貌似python
根据isatty
决定是否使用缓冲。
我使用了这个脚本(来自 Trick an application into thinking its stdout is a terminal, not a pipe):
faketty() {
script -qfc "$(printf "%q " "$@")" /dev/null
}
有效:
% faketty python3 a.py | cat
input
(而且它是行缓冲的)
默认情况下,Python 的 print()
函数将其输出定向到 sys.stdout
,其文档指定为:
When interactive, stdout
and stderr
streams are line-buffered.
Otherwise, they are block-buffered like regular text files. You can
override this value with the -u
command-line option.
请注意,这些文档在 sys.stdout
的缓冲模式下没有为一般环境影响留出空间,例如 stdbuf
命令的影响:如果 [=14] 是无缓冲的=] 选项被使用(或者,等效地,如果设置了环境变量 PYTHONUNBUFFERED
),否则如果交互则行缓冲,如果非交互则块缓冲。
程序可以控制自己的缓冲,stdbuf
的文档承认:
NOTE: If COMMAND adjusts the buffering of its standard streams ('tee'
does for e.g.) then that will override corresponding settings changed
by 'stdbuf'. Also some filters (like 'dd' and 'cat' etc.) don't use
streams for I/O, and are thus unaffected by 'stdbuf' settings.
由于 Python 明确指定了缓冲细节,因此可以合理地预期它实际上确实肯定地管理其缓冲,从而提出 stdbuf
的任何影响。
在 Python 中给出以下程序:
import sys
print("input")
while True:
pass
和 C 中的等价物:
#include <stdio.h>
int main() {
printf("input\n");
while(1);
return 0;
}
当我使用 cat
对程序进行管道传输时,默认情况下输出是缓冲的(而不是行缓冲的)。结果,我没有输出:
% python3 ./a.py | cat
(empty)
% ./a.out | cat
(empty)
我可以使用 stdbuf
切换回行缓冲:
% stdbuf -oL ./a.out | cat
input
但这不适用于 Python:
% stdbuf -oL python3 a.py | cat
(empty)
知道为什么吗?我知道 python3 -u
的存在,但我想要行缓冲,而不是 "no buffering" 并且我希望此命令行也适用于其他语言。命令 unbuffer
似乎也有效,但我想了解为什么 stdbuf
在这里不起作用。
貌似python
根据isatty
决定是否使用缓冲。
我使用了这个脚本(来自 Trick an application into thinking its stdout is a terminal, not a pipe):
faketty() {
script -qfc "$(printf "%q " "$@")" /dev/null
}
有效:
% faketty python3 a.py | cat
input
(而且它是行缓冲的)
默认情况下,Python 的 print()
函数将其输出定向到 sys.stdout
,其文档指定为:
When interactive,
stdout
andstderr
streams are line-buffered. Otherwise, they are block-buffered like regular text files. You can override this value with the-u
command-line option.
请注意,这些文档在 sys.stdout
的缓冲模式下没有为一般环境影响留出空间,例如 stdbuf
命令的影响:如果 [=14] 是无缓冲的=] 选项被使用(或者,等效地,如果设置了环境变量 PYTHONUNBUFFERED
),否则如果交互则行缓冲,如果非交互则块缓冲。
程序可以控制自己的缓冲,stdbuf
的文档承认:
NOTE: If COMMAND adjusts the buffering of its standard streams ('tee' does for e.g.) then that will override corresponding settings changed by 'stdbuf'. Also some filters (like 'dd' and 'cat' etc.) don't use streams for I/O, and are thus unaffected by 'stdbuf' settings.
由于 Python 明确指定了缓冲细节,因此可以合理地预期它实际上确实肯定地管理其缓冲,从而提出 stdbuf
的任何影响。