如何在Python3中实现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文件描述符在操作系统内核中

我想写一个类,它可以作为真正的文件描述符。其.fileno()方法应返回一个文件描述符,该描述符提供POSIX系统所需的所有服务

这是我第一次涉足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 to
subprocess.Popen
传递所需的其他调用是什么?如果您想在subprocess.Popen中使用StringIO,也许您应该结束这个问题并询问您真正想知道的内容。