[英]How to open <del>named pipe</del>character device special file for reading and writing in Python
我有一个在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.
例如,如果我尝试open(pathname, "r+")
,我会得到该消息,如果我尝试fd=os.open(...)
后跟os.fdopen(fd, "r+", ...)
我得到相同的消息fd=os.open(...)
os.fdopen(fd, "r+", ...)
问:Python3程序在文本中写入和读取文本的首选方法是什么? 命名管道 角色设备?
编辑:
哎呀! 我假设我正在处理一个命名管道,因为该服务的文档将其描述为“管道”,因为它在用户模式服务运行之前不会出现在文件系统中。 但是,Linux file
实用程序说它实际上是一个字符设备特殊文件。
你可以使用pexpect
。 以下是使用两个python模块的示例:
caller.py
import pexpect
proc = pexpect.spawn('python3 backwards.py')
proc.expect(' > ')
while True:
n = proc.sendline(input('Feed me - '))
proc.expect(' > ')
print(proc.before[n+1:].decode())
backwards.py
x = ''
while True:
x = input(x[::-1] + ' > ')
caller.py
正在使用“Pseudo-TTY设备”与backwards.py
交谈。 我们使用expect
(以及before
属性)提供sendline
输入和捕获输入。
出现该问题是因为试图使用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
两次,但幸运的是,双关闭在这里是无害的(第二次close
什么也没做,意识到它已经关闭)。
看起来你需要为阅读和写入创建单独的句柄:打开读/写只需要一个搜索方法。 我无法弄清楚如何超时读取,所以最好添加一个开启器(参见io.open
的docstring),以非阻塞模式打开阅读器。 我在名为/tmp/test_pipe
的命名管道上设置了一个简单的echo服务:
In [1]: import io
In [2]: import os
In [3]: nonblockingOpener = lambda name, flags:os.open(name, flags|os.O_NONBLOCK)
In [4]: reader = io.open('/tmp/test_pipe', 'r', opener = nonblockingOpener)
In [5]: writer = io.open('/tmp/test_pipe', 'w')
In [6]: writer.write('Hi have a line\n')
In [7]: writer.flush()
In [8]: reader.readline()
Out[8]: 'You said: Hi have a line\n'
In [9]: reader.readline()
''
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.