繁体   English   中英

如何在Python中打开<del>命名管道</ del>字符设备专用文件进行读写

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM