我有这个 python 脚本,它的作用是充当服务器,它从重定向到 fifo 的 stdin 读取命令:
test.py:
while True:
try:
line = input()
except EOFError:
break
print(f'Received: {line}')
在 bash 中运行命令:
mkfifo testfifo
test.py < testfifo &
echo word > testfifo
而不是打印该行收到后,脚本因错误而退出:
Traceback (most recent call last):
File "test.py", line 5, in <module>
line = input()
^^^^^^^
RuntimeError: input(): lost sys.stdin
[1]+ Exit 1 test.py < testfifo
我读过一些答案,这些答案说始终需要有一个写入器来打开 fifo。所以我也尝试运行:
sleep 100 > testfifo &
同样的错误。我还尝试用以下内容替换
input()
行:
line = sys.stdin.readline()
而所做的只是给我这个错误:
AttributeError: 'NoneType' object has no attribute 'readline'
我在 Windows 上使用 mingw64,我怀疑这可能是 mingw 的错误。有任何想法吗?谢谢。
编辑:由于这个问题看起来相当无望并且超出了我的控制范围,所以我现在选择只使用 UDP 服务器。 Bash 支持重定向到
/dev/utp/host/port
,这使得这很容易做到。
你观察到的行为是因为当你将 python 脚本的 stdin 重定向到 FIFO,而没有其他进程写入 FIFO 时,
sys.stdin
在 Windows 上的 mingw64 中的行为会变得不可预测。这很可能是 mingw64 中的一个错误,或者至少是 Windows 上 FIFO 处理方式的一个怪癖。
尽管在你的原始问题中寻求基于 FIFO 的解决方案似乎没有希望,但让我们探索一些解决方法,以防 FIFO 是绝对要求:
解决方法 1:使用线程化读取器
与其依赖
input()
或
sys.stdin.readline()
,不如创建一个单独的线程来处理来自 FIFO 的读取。这可以防止主线程在等待输入时阻塞,从而可能避免错误。
import threading
import os
def reader_thread(fifo_path):
with open(fifo_path, 'r') as fifo:
while True:
line = fifo.readline()
if not line:
break
print(f'Received: {line.strip()}')
if __name__ == '__main__':
fifo_path = 'testfifo'
if not os.path.exists(fifo_path):
os.mkfifo(fifo_path)
reader = threading.Thread(target=reader_thread, args=(fifo_path,))
reader.start()
reader.join()
解决方法 2:使用命名管道进行双向通信
与其仅仅依靠 stdin,不如探索使用命名管道来实现 python 脚本和将数据写入其中的进程之间的双向通信。这将允许更强大的交互并可能解决问题。
import os
def server(fifo_in, fifo_out):
with open(fifo_in, 'r') as fifo_read, open(fifo_out, 'w') as fifo_write:
while True:
line = fifo_read.readline()
if not line:
break
message = f'Received: {line.strip()}'
print(message)
fifo_write.write(message + '\n')
fifo_write.flush()
if __name__ == '__main__':
fifo_in = 'testfifo_in'
fifo_out = 'testfifo_out'
if not os.path.exists(fifo_in):
os.mkfifo(fifo_in)
if not os.path.exists(fifo_out):
os.mkfifo(fifo_out)
server(fifo_in, fifo_out)
然后,你可以修改你的 bash 脚本以使用这两个 FIFO 进行发送和接收。
请记住,即使使用这些解决方法,mingw64 上与 FIFO 相关的行为也可能不一致。如果你遇到持续存在的问题,你可能需要考虑使用 UDP 套接字(如你所建议的)或探索特定于 Windows 的进程间通信机制(如命名管道)作为更可靠的替代方案。
标签:python,bash,mingw,fifo,mkfifo From: 78770272