管道仅在直接运行脚本时有效使用shebang?

问题描述

我编写了两个 Python 脚本来试验管道如何与 Python 配合使用。

foo1.py:

#! /Library/Frameworks/Python.framework/Versions/3.9/bin/python3

import time

for i in range(10):
    print(i,flush=True)
    time.sleep(1)

foo2.py:

#! /Library/Frameworks/Python.framework/Versions/3.9/bin/python3

import time
import sys

print("2 start")

for l in sys.stdin:
    print(int(l)+100)
    time.sleep(0.05)

当我直接运行这些 (> ./foo1.py | ./foo2.py) 时,我得到了每个数字之间有 1 秒延迟的预期输出

2 start
100
101
102
...

但是,当我使用 Python (python3 foo1.py | python3 foo2.py) 运行这些时,直到 10 秒后才会生成任何输出(甚至 2 start),当整个输出被一次打印时。我很困惑,因为这些命令似乎应该是相同的。任何有关此处差异的见解将不胜感激。我正在使用 Python 3.9.0 运行 macOS 11.3.1。

解决方法

更新:我找到了解决方案。不久前,我在使用不同版本的 python3 时遇到问题,所以我为 python3 设置了一个 Fish 别名:

function python3
    command python3.9 $argv
end

删除这个别名解决了这个问题。进一步的实验表明,鱼的功能以一种意想不到的方式干扰了线路缓冲。 python foo1.py | ./foo2.py./foo1.py | python foo2.py 都产生了正确的结果。另外,当我在 shell 中重新定义一个函数时

function test_py
    command python3.9 $argv
end

然后 test_py foo1.py | test_py foo2.py 完美运行。只有在单独的 fish 脚本(包括 .config/fish/config.fish)中定义了该函数时,才会出现意外行为。