Python 读取命名管道
- 2024-10-30 08:36:00
- admin 原创
- 40
问题描述:
我在 linux 中有一个命名管道,我想从 python 中读取它。问题是 python 进程不断“消耗”一个核心(100%)。我的代码如下:
FIFO = '/var/run/mypipe'
os.mkfifo(FIFO)
with open(FIFO) as fifo:
while True:
line = fifo.read()
我想问一下“睡眠”是否会对这种情况有所帮助,或者进程是否会丢失一些来自管道的输入数据。我无法控制输入,所以我不知道数据输入的频率。我读过关于 select 和 poll 的文章,但我没有找到任何适合我的问题的例子。最后,我想问一下 100% 的使用率是否会对数据输入产生任何影响(丢失或其他什么?)。
编辑:我不想中断循环。我希望进程连续运行并“监听”来自管道的数据。
解决方案 1:
在典型的 UNIX 方式中,read(2)
返回 0 字节来指示文件结束,这可能意味着:
文件中没有更多字节
套接字的另一端已关闭连接
作者关闭了管道
在您的情况下,fifo.read()
返回一个空字符串,因为写入器已经关闭了其文件描述符。
您应该检测到这种情况并跳出循环:
reader.py:
import os
import errno
FIFO = 'mypipe'
try:
os.mkfifo(FIFO)
except OSError as oe:
if oe.errno != errno.EEXIST:
raise
print("Opening FIFO...")
with open(FIFO) as fifo:
print("FIFO opened")
while True:
data = fifo.read()
if len(data) == 0:
print("Writer closed")
break
print('Read: "{0}"'.format(data))
示例会话
1 号航站楼:
$ python reader.py
Opening FIFO...
<blocks>
2 号航站楼:
$ echo -n 'hello' > mypipe
1 号航站楼:
FIFO opened
Read: "hello"
Writer closed
$
更新1-持续重新开放
您表示您想继续监听管道上的写入操作,甚至在写入器关闭之后也是如此。
为了有效地做到这一点,你可以(也应该)利用以下事实:
正常情况下,打开 FIFO 会阻塞,直到另一端也打开为止。
在这里,我添加了另一个循环open
。read
这样,一旦管道关闭,代码将尝试重新打开它,这将被阻塞,直到另一个写入器打开管道:
import os
import errno
FIFO = 'mypipe'
try:
os.mkfifo(FIFO)
except OSError as oe:
if oe.errno != errno.EEXIST:
raise
while True:
print("Opening FIFO...")
with open(FIFO) as fifo:
print("FIFO opened")
while True:
data = fifo.read()
if len(data) == 0:
print("Writer closed")
break
print('Read: "{0}"'.format(data))
1 号航站楼:
$ python reader.py
Opening FIFO...
<blocks>
2 号航站楼:
$ echo -n 'hello' > mypipe
1 号航站楼:
FIFO opened
Read: "hello"
Writer closed
Opening FIFO...
<blocks>
2 号航站楼:
$ echo -n 'hello' > mypipe
1 号航站楼:
FIFO opened
Read: "hello"
Writer closed
Opening FIFO...
<blocks>
... 等等。
您可以通过阅读man
管道页面了解更多信息:
PIPE(7) - Linux 程序员手册
FIFO(7) - Linux 程序员手册
解决方案 2:
(多年后)如果我理解 OP 的用例,那么使用for ... in ...
正是所需的:
import os
FIFO = 'myfifo'
os.mkfifo(FIFO)
with open(FIFO) as fifo:
for line in fifo:
print(line)
这个程序耐心地等待来自 fifo 的输入,直到提供输入,然后将其打印在屏幕上。在此期间不使用任何 CPU。
这也是 Python 中更惯用的方式,因此我推荐它而不是直接使用 read()。
如果客户端写入 fifo 关闭,则 for 循环结束,程序退出。如果您希望它重新打开 fifo 以等待下一个客户端打开它,您可以将该for
部分放入 while 循环中:
import os
FIFO = 'myfifo'
os.mkfifo(FIFO)
while True:
with open(FIFO) as fifo:
for line in fifo:
print(line)
这将重新打开 fifo 并照常等待。
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件