簡體   English   中英

Python:檢查命名管道是否有數據

[英]Python: Check if named pipe has data

我的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)

如果管道中沒有數據,我會得到b"" ,然后退出。 如果管道中有數據,它會獲得一次異常,重試,然后獲取數據。 好像我做錯了什么,可能會遇到奇怪的競爭條件。 有沒有更好的方法來做到這一點?

如果您可以更改客戶端的代碼,而不是UNIX域套接字 ,我不會使用命名管道,因為它們支持數據報:

import errno, fcntl, os, socket

服務器:

# 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)

客戶:

sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
sock.sendto('Hello!', 'pipe_test.fifo')

但您可能希望研究multithreading而不是使用非阻塞套接字。

這不是真正的答案,但如果它對任何人都有用,這就是我用另一個線程做的。

class QueryThread(threading.Thread):

    def __init__(self, args=(), kwargs=None):
        threading.Thread.__init__(self, args=(), kwargs=None)
        self.daemon = True
        self.buf = []
        if not general.f_exists("pipe"):
            os.mkfifo("pipe")

    def run(self):
        f = open("pipe")
        while True:
            try:
                query = next(f).replace("\n", "")
                if query != "":
                    self.buf.append(query)
                    print("Read in new query from pipe: {}, buf = {}".format(query, self.buf))
            except StopIteration: # not a pipe error, just means no data is left, so time to re-open
                f.close()
                f = open("pipe")
        f.close()

    def get_query(self):
        if len(self.buf) == 0: return ""
        query = self.buf[0]
        self.buf.__delitem__(0)
        return query

它將新行消除的消息保留在緩沖區中。 您可以從另一個線程調用get_query方法並獲取收到的最后一條消息。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM