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