繁体   English   中英

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

[英]How can I implement a POSIX file descriptor in Python 3?

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

这是我第一次涉足POSIX系统编程,所以我可能会误解事情。

底层动机是使用一个内存Python对象作为欲望stdinstdout 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM