gpt4 book ai didi

python - 非阻塞fifo

转载 作者:行者123 更新时间:2023-11-28 18:28:39 26 4
gpt4 key购买 nike

我如何在两个 python 进程之间创建一个 fifo,以便在读取器无法处理输入时允许丢弃行?

  • 如果读者试图readreadline 比作者写的更快,它应该阻止。
  • 如果读者不能像作者写的那样快,作者不应该阻止。行不应该被缓冲(一次一行除外)并且只有最后一行写入的内容应该被读取器在下一次 readline 尝试时接收。

这是否可以通过命名的 fifo 实现,或者是否有任何其他简单的方法可以实现这一点?

最佳答案

以下代码使用命名的 FIFO 允许两个脚本之间进行通信。

  • 如果读者试图比作者更快地阅读,它就会阻塞。
  • 如果读者跟不上作者,作者不会阻止。
  • 操作是面向缓冲区的。当前未实现面向行的操作。
  • 此代码应被视为概念验证。延迟和缓冲区大小是任意的。

代码

import argparse
import errno
import os
from select import select
import time

class OneFifo(object):
def __init__(self, name):
self.name = name

def __enter__(self):
if os.path.exists(self.name):
os.unlink(self.name)
os.mkfifo(self.name)
return self

def __exit__(self, exc_type, exc_value, exc_traceback):
if os.path.exists(self.name):
os.unlink(self.name)

def write(self, data):
print "Waiting for client to open FIFO..."
try:
server_file = os.open(self.name, os.O_WRONLY | os.O_NONBLOCK)
except OSError as exc:
if exc.errno == errno.ENXIO:
server_file = None
else:
raise
if server_file is not None:
print "Writing line to FIFO..."
try:
os.write(server_file, data)
print "Done."
except OSError as exc:
if exc.errno == errno.EPIPE:
pass
else:
raise
os.close(server_file)

def read_nonblocking(self):
result = None
try:
client_file = os.open(self.name, os.O_RDONLY | os.O_NONBLOCK)
except OSError as exc:
if exc.errno == errno.ENOENT:
client_file = None
else:
raise
if client_file is not None:
try:
rlist = [client_file]
wlist = []
xlist = []
rlist, wlist, xlist = select(rlist, wlist, xlist, 0.01)
if client_file in rlist:
result = os.read(client_file, 1024)
except OSError as exc:
if exc.errno == errno.EAGAIN or exc.errno == errno.EWOULDBLOCK:
result = None
else:
raise
os.close(client_file)
return result

def read(self):
try:
with open(self.name, 'r') as client_file:
result = client_file.read()
except OSError as exc:
if exc.errno == errno.ENOENT:
result = None
else:
raise
if not len(result):
result = None
return result

def parse_argument():
parser = argparse.ArgumentParser()
parser.add_argument('-c', '--client', action='store_true',
help='Set this flag for the client')
parser.add_argument('-n', '--non-blocking', action='store_true',
help='Set this flag to read without blocking')
result = parser.parse_args()
return result

if __name__ == '__main__':
args = parse_argument()
if not args.client:
with OneFifo('known_name') as one_fifo:
while True:
one_fifo.write('one line')
time.sleep(0.1)
else:
one_fifo = OneFifo('known_name')
while True:
if args.non_blocking:
result = one_fifo.read_nonblocking()
else:
result = one_fifo.read()
if result is not None:
print result

服务器检查客户端是否打开了FIFO。如果 client 打开了 FIFO,server 写入一行。否则,服务器 继续运行。我已经实现了一个非阻塞读取,因为阻塞读取会导致一个问题:如果 server 重新启动,大多数时候 client 会保持阻塞并且永远不会恢复。使用非阻塞客户端,更容易容忍服务器重启。

输出

[user@machine:~] python onefifo.py
Waiting for client to open FIFO...
Waiting for client to open FIFO...
Writing line to FIFO...
Done.
Waiting for client to open FIFO...
Writing line to FIFO...
Done.

[user@machine:~] python onefifo.py -c
one line
one line

注意事项

在启动时,如果服务器 检测到 FIFO 已经存在,它会删除它。这是通知 clients server 已重启的最简单方法。此通知通常会被 client 的阻塞版本忽略。

关于python - 非阻塞fifo,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39233663/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com