如何在Python 3中实现POSIX文件描述符?



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

这是我第一次接触POSIX系统编程,所以我可能会误解很多东西。

潜在的动机是希望使用内存中的Python对象作为stdinstdoutsubprocess.Popen构造函数的变量,而不必依赖于临时文件或内存映射文件。但是我对能够完成工作的一些聪明的技巧不感兴趣——我真的希望有一个能够回答所有相关系统调用的Python实现。

你不能。POSIX文件描述符在Python世界之外的操作系统内核中被跟踪;你不能在Python代码中模拟它们。

如果您想要一个类在传递给系统调用时可以用作文件,那么它需要有一个fileno(),它是一个真正的操作系统文件描述符。一种不涉及硬盘的方法是使用管道,因为管道有文件描述符,然后系统调用可以写入这些文件描述符。

我确实写了一个类,使用这种技术做了另一个答案。它并没有真正做你想做的事情,但是使用管道的技术应该是可行的:

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插入新的文件描述符。在内核空间中运行的代码与正常的("用户模式")代码非常不同。

我建议你看一下子进程。PIPE,以及subprocess上的stdout/stdin/stderr属性或communication()方法。Popen对象?这将允许您启动子流程,读取它输出的数据,并完全控制发送给它的数据。(我认为这是你真正想做的……)如果您很好奇,那么当您使用这个程序时,您可以查看subprocess.py源代码,看看它是如何工作的。

有一个子进程的例子。管这里。

或者,如果您真的想在Python中实现一个完整的文件系统,请查看FUSE,它是Python绑定。FUSE包含一个在内核中运行的C模块,并处理对某个目录的文件系统请求。它通过将它们传递给可以用Python编写的用户空间程序来处理它们。您可以从单独的 Python程序打开这些文件,以获得它们的文件描述符。这有点复杂,可能不是初学者开始的最佳地方。

相关内容

  • 没有找到相关文章

最新更新