Python脚本stdin重定向至FIFO引发RuntimeError问题求助
问题描述
我写了一个作为服务器运行的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()替换为sys.stdin.readline()后,又出现新错误:
AttributeError: 'NoneType' object has no attribute 'readline'
当前使用Windows下的mingw64环境,怀疑是mingw的bug,求解决思路。
编辑:暂时无法解决该问题,已改用UDP服务器方案,bash支持将内容重定向到/dev/udp/host/port,实现更简便。
解决思路
1. 直接操作FIFO文件句柄,绕过stdin重定向
Mingw64的stdin重定向到FIFO时,可能存在句柄异常回收的问题,建议直接在Python中打开FIFO文件进行读取:
修改test.py:
import time def main(): with open('testfifo', 'r') as fifo: while True: # 读取一行,若FIFO暂时无内容则短暂休眠后重试 line = fifo.readline() if not line: time.sleep(0.1) continue print(f'Received: {line.strip()}') if __name__ == '__main__': main()
启动方式改为直接运行脚本,不需要重定向stdin:
mkfifo testfifo python test.py & echo word > testfifo
这种方式避免依赖全局的sys.stdin对象,减少Mingw环境下的兼容性问题。
2. 检查并更新Mingw64版本
部分旧版本的Mingw64在FIFO实现上存在bug,尝试更新到最新稳定版,可能会修复句柄管理异常的问题。
3. 替代方案:UDP服务器(已验证可行)
正如你所尝试的,bash支持通过/dev/udp/host/port发送数据,Python实现UDP服务器非常简单,示例如下:
UDP服务器脚本udp_server.py:
import socket def main(): udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) udp_socket.bind(('127.0.0.1', 9999)) print('UDP server started on 127.0.0.1:9999') while True: data, addr = udp_socket.recvfrom(1024) print(f'Received from {addr}: {data.decode().strip()}') if __name__ == '__main__': main()
启动服务器后,在bash中发送数据:
echo "word" > /dev/udp/127.0.0.1/9999
这种方案在Mingw64环境下兼容性更好,实现也更简洁。
内容的提问来源于stack exchange,提问作者Verpous
相关产品推荐
相关产品推荐

