我有一个在Linux机器上运行的服务,它创建一个命名管道字符设备特殊文件,我想编写一个Python3程序,通过编写文本命令和从管道设备读取文本回复来与服务进行通信.我没有该服务的源代码.
我可以使用os.open(named_pipe_pathname,os.O_RDWR),我可以使用os.read(…)和os.write(…)来读取和写入它,但这很痛苦,因为我必须写我自己的代码在字节和字符串之间转换,我必须编写自己的readline(…)函数等.
我宁愿使用Python3 io对象来读取和写入管道设备,但我能想到的每一种方法都会返回相同的错误:
io.UnsupportedOperation: File or stream is not seekable.
例如,如果我尝试打开(路径名,“r”),我会收到该消息,如果我尝试fd = os.open(…)后跟os.fdopen(fd,“r”,我得到相同的消息) …).
问:Python3程序在命名管道字符设备上写入和读取文本的首选方法是什么?
编辑:
哎呀!我假设我正在处理一个命名管道,因为该服务的文档将其描述为“管道”,因为它在用户模式服务运行之前不会出现在文件系统中.但是,Linux文件实用程序说它实际上是一个字符设备特殊文件.
最佳答案
出现此问题是因为尝试在读写模式下使用io.open会隐式尝试将基础文件包装在io.BufferedRandom中(如果在文本模式下,则将其包装在io.TextIOWrapper中),这假定基础文件不仅被读取/ write,但随机访问,它基于此需要自由(寻求隐式).有一个单独的类io.BufferedRWPair,用于读/写管道(docstring特别提到它用于套接字和双向管道).
您可以通过逐层手动包装来模仿io.open的效果,以产生相同的最终结果.具体来说,对于文本模式包装器,您可以执行以下操作:
rawf = io.FileIO(named_pipe_pathname,mode="rb+")
with io.TextIOWrapper(io.BufferedRWPair(rawf,rawf),encoding='utf-8',write_through=True) as txtf:
del rawf # Remove separate reference to rawf; txtf manages lifetime now
# Example use that works (but is terrible form,since communicating with
# oneself without threading,select module,etc.,is highly likely to deadlock)
# It works for this super-simple case; presumably you have some parallel real code
txtf.write("abcé\n")
txtf.flush()
print(txtf.readline(),flush=True)
我相信当txtf关闭时,这将关闭rawf两次,但幸运的是,双关闭在这里是无害的(第二次关闭什么也没做,意识到它已经关闭).