Как я могу реализовать дескриптор файла POSIX в Python 3? - PullRequest
4 голосов
/ 31 декабря 2011

Я хотел бы написать класс, который может вести себя как настоящий файловый дескриптор.Его метод .fileno () должен возвращать файловый дескриптор, который предоставляет все службы, которые ожидает система POSIX.

Это мой первый набег на системное программирование POSIX, так что я мог бы плохо понимать вещи.

Основной мотивацией является желание использовать объект Python в памяти в качестве stdin или stdout kwarg для конструктора subprocess.Popen без необходимости полагаться на временные или отображаемые в память файлы.Но меня не интересует какой-то хитрый прием, который бы справился с работой - я действительно хочу иметь реализацию Python, способную отвечать на все соответствующие системные вызовы.

Ответы [ 3 ]

2 голосов
/ 31 декабря 2011

Если вы хотите иметь класс, который можно использовать в качестве файла при передаче системным вызовам, он должен иметь 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])
2 голосов
/ 31 декабря 2011

Вы не можете.Дескрипторы файлов POSIX отслеживаются в ядре операционной системы, за пределами мира Python;Вы не можете имитировать их в коде Python.

0 голосов
/ 22 февраля 2012

Это мой первый опыт программирования системы POSIX, так что я могу очень плохо понимать вещи.

Да.

Файловые дескрипторы POSIX - это просто числа - они не объекты, поэтому вы не можете переопределить их методы. Например, 0, 1 и 2 - все [обычно] допустимые файловые дескрипторы.

«соответствующие системные вызовы» встроены в ядро ​​Linux. Само ядро ​​Linux поддерживает список, который отображает файловые дескрипторы на некоторый внутренний объект ядра (у которого есть методы!), Но вы не можете вставить новый файловый дескриптор из Python. Код, выполняемый в пространстве ядра, сильно отличается от обычного кода («пользовательский режим»).

Могу ли я предложить вам взглянуть на subprocess.PIPE и либо на свойства stdout / stdin / stderr, либо на метод connect () объектов subprocess.Popen? Это позволит вам запустить подпроцесс, прочитать данные, которые он выводит, и иметь полный контроль над данными, которые ему отправляются. (Я думаю, это то, что вы действительно пытаетесь сделать ...). Если вам интересно, то, поиграв с этим, вы можете посмотреть на исходный код subprocess.py, чтобы увидеть, как он работает.

Вот пример подпроцесса. ТРУБА здесь .

В качестве альтернативы, если вы действительно хотите реализовать полную файловую систему на Python, посмотрите на FUSE , и это привязки Python . FUSE содержит модуль C, который работает в ядре и обрабатывает запросы файловой системы для определенного каталога. Он обрабатывает их, передавая их в пользовательскую программу, которая может быть написана на Python. Вы можете открыть эти файлы из отдельной программы Python, чтобы получить к ним файловый дескриптор. Это довольно сложно и, вероятно, не лучшее место для начинающего.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...