[英]How can I implement a POSIX file descriptor in Python 3?
我想寫一個可以表現為真正的文件描述符的類。 它的.fileno()方法應返回一個文件描述符,它提供POSIX系統所需的所有服務。
這是我第一次涉足POSIX系統編程,所以我可能會誤解事情。
底層動機是使用一個內存Python對象作為欲望stdin
或stdout
kwarg到subprocess.Popen
構造,而不必依賴於臨時或存儲器映射的文件。 但是我對一些聰明的技巧不感興趣 - 我真的希望有一個能夠回答所有相關系統調用的Python實現。
你不能。 在Python世界之外的操作系統內核中跟蹤POSIX文件描述符; 你無法在Python代碼中模擬它們。
如果你想要一個可以在傳遞給系統調用時用作文件的類,它需要有一個fileno(),它是一個真正的OS文件描述符。 在不觸及硬盤的情況下執行此操作的一種方法是使用管道,因為它們具有文件描述符,然后系統調用可以寫入這些文件描述符。
我寫了一個類,用另一個答案使用這種技術做了一些事情。 它並沒有真正做你想做的事情,但使用管道的技術應該可以讓你:
import io
import logging
import os
import select
import subprocess
import time
import threading
LOG_FILENAME = 'output.log'
logging.basicConfig(filename=LOG_FILENAME,level=logging.DEBUG)
class StreamLogger(io.IOBase):
def __init__(self, level):
self.level = level
self.pipe = os.pipe()
self.thread = threading.Thread(target=self._flusher)
self.thread.start()
def _flusher(self):
self._run = True
buf = b''
while self._run:
for fh in select.select([self.pipe[0]], [], [], 0)[0]:
buf += os.read(fh, 1024)
while b'\n' in buf:
data, buf = buf.split(b'\n', 1)
self.write(data.decode())
time.sleep(1)
self._run = None
def write(self, data):
return logging.log(self.level, data)
def fileno(self):
return self.pipe[1]
def close(self):
if self._run:
self._run = False
while self._run is not None:
time.sleep(1)
os.close(self.pipe[0])
os.close(self.pipe[1])
這是我第一次涉足POSIX系統編程,所以我可能會誤解事情。
是的。
POSIX文件描述符只是數字 - 它們不是對象,因此您無法覆蓋它們的方法。 例如,0,1和2都是[通常]有效的文件描述符。
“相關系統調用”內置於Linux內核中。 Linux內核本身維護一個列表,將文件描述符映射到某個內部內核對象(它有方法!),但是你不能從Python插入新的文件描述符。 在內核空間中運行的代碼與普通(“用戶模式”)代碼非常不同。
我可以建議您查看subprocess.PIPE,以及stdout / stdin / stderr屬性或subprocess.Popen對象上的communic()方法嗎? 這將允許您啟動子進程,讀取它輸出的數據,並完全控制發送給它的數據。 (我認為這是你真正想做的......)。 如果你很好奇,那么當你玩這個時,你可以查看subprocess.py源代碼,看看它是如何工作的。
有subprocess.PIPE的例子在這里 。
或者,如果您確實想在Python中實現完整的文件系統,請查看FUSE ,它是Python綁定 。 FUSE包含一個在內核中運行的C模塊,並處理某個目錄的文件系統請求。 它通過將它們傳遞給用戶空間程序來處理它們,該程序可以用Python編寫。 您可以從單獨的 Python程序中打開這些文件,以獲取文件描述符。 這有點復雜,可能不是初學者開始的最佳場所。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.