Python:检查命名管道是否有数据

sud*_*udo 5 python named-pipes

我的 Unix 系统上有一个 Python3 进程一直在运行,我希望能够通过命名管道从其他偶尔运行的进程中随机向它发送数据。如果命名管道没有数据,我希望我的进程继续做其他事情,所以我需要检查它是否有数据而不阻塞

我不知道如何在不打开它的情况下进行检查,但是除非我设置了非阻塞标志,否则无法打开块。如果我设置了标志,如果我在读取之前或期间碰巧写入管道,它就会崩溃。

这是我设法做到的最好的:

import os

fifo = "pipe_test.fifo"
done = False
fd = os.open(fifo, os.O_RDONLY | os.O_NONBLOCK)
while not done:
    try:
        s = os.read(fd, 1024) # buffer size may need tweaking
        print(s)
        done = True
    except BlockingIOError as e:
        pass
os.close(fd)
Run Code Online (Sandbox Code Playgroud)

如果管道中没有数据,我得到b"",然后退出。如果管道中有数据,它会得到一次异常,重试,然后获取数据。好像我做错了什么,可能会遇到奇怪的竞争条件。有没有更好的方法来做到这一点?

kay*_*kay 4

如果您可以更改客户端代码,我不会使用命名管道,而是使用UNIX 域套接字,因为它们支持数据报:

import errno, fcntl, os, socket
Run Code Online (Sandbox Code Playgroud)

服务器:

# bind socket
sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
sock.bind('pipe_test.fifo')
# set socket non-blocking
fcntl.fcntl(sock.fileno(), fcntl.F_SETFL, os.O_NONBLOCK)

# get a datagram
try:
    datagram = sock.recv(1024)
except (OSError, socket.error) as ex:
    if ex.errno not in (errno.EINTR, errno.EAGAIN):
        raise
else:
    print('Datagram: %r' % datagram)
Run Code Online (Sandbox Code Playgroud)

客户:

sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
sock.sendto('Hello!', 'pipe_test.fifo')
Run Code Online (Sandbox Code Playgroud)

但您可能想研究一下multithreading而不是使用非阻塞套接字。