如何在Python3中实现POSIX文件描述符?
我想写一个类,它可以作为真正的文件描述符。其.fileno()方法应返回一个文件描述符,该描述符提供POSIX系统所需的所有服务 这是我第一次涉足POSIX系统编程,所以我可能会对事情产生严重误解如何在Python3中实现POSIX文件描述符?,python,file-io,python-3.x,posix,file-descriptor,Python,File Io,Python 3.x,Posix,File Descriptor,我想写一个类,它可以作为真正的文件描述符。其.fileno()方法应返回一个文件描述符,该描述符提供POSIX系统所需的所有服务 这是我第一次涉足POSIX系统编程,所以我可能会对事情产生严重误解 基本动机是希望使用内存中的Python对象作为stdin或stdoutkwarg到subprocess.Popen构造函数,而不必依赖临时或内存映射文件。但我对完成这项工作的一些巧妙技巧不感兴趣——我真的希望有一个能够回答所有相关系统调用的Python实现。你不能。POSIX文件描述符在操作系统内核中
基本动机是希望使用内存中的Python对象作为
stdin
或stdout
kwarg到subprocess.Popen
构造函数,而不必依赖临时或内存映射文件。但我对完成这项工作的一些巧妙技巧不感兴趣——我真的希望有一个能够回答所有相关系统调用的Python实现。你不能。POSIX文件描述符在操作系统内核中进行跟踪,而不是在Python世界中;你不能在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以及subprocess.Popen对象上的stdout/stdin/stderr属性或communicate()方法吗?这将允许您启动子流程,读取它输出的数据,并完全控制发送给它的数据。(我想这就是你真正想做的…)。如果您很好奇,那么当您玩过这个之后,您可以查看subprocess.py源代码来了解它是如何工作的
下面是subprocess.PIPE的一个示例
或者,如果您真的想在Python中实现一个完整的文件系统,请查看,这是非常有用的。FUSE包含一个在内核中运行的C模块,用于处理特定目录的文件系统请求。它通过将它们传递给可以用Python编写的用户空间程序来处理它们。您可以从单独的Python程序中打开这些文件,以获取它们的文件描述符。这有点复杂,对于初学者来说可能不是最好的起点。Python“包装”了Posix文件描述符。你有你需要的所有访问权限。请定义“所有相关系统调用”。支持打开、关闭、读取和写入。您还需要哪些其他调用?@S.Lott:StringIO对象(例如)作为
stdin
或stdout
kwarg tosubprocess.Popen
传递所需的其他调用是什么?如果您想在subprocess.Popen中使用StringIO,也许您应该结束这个问题并询问您真正想知道的内容。