Перенос класса, производного от файла Python2, на Python 3

#python #python-3.x #python-2.x #porting

#python #python-3.x #python-2.x #перенос

Вопрос:

Я переношу некоторый устаревший код Python 2, и у меня есть этот класс:

 class myfile(file):
    "Wrapper for file object whose read member returns a string buffer"
    def __init__ (self, *args):
        return file.__init__ (self, *args)

    def read(self, size=-1):
        return create_string_buffer(file.read(self, size))
  

Он используется как файловый объект:

 self._file = myfile(name, mode, buffering)
self._file.seek(self.si*self.blocksize)
  

Я пытаюсь реализовать это в Python 3 следующим образом:

 class myfile(io.FileIO):
    "Wrapper for file object whose read member returns a string buffer"
    def __init__(self, name, mode, *args, **kwargs):
        super(myfile, self).__init__(name, mode, closefd=True, *args, **kwargs)

    def read(self, size=-1):
        return create_string_buffer(self.read(size))
  

Проблема в том, что конструктор для FileIO не принимает buffering аргумент, и Python выдает TypeError: fileio() takes at most 3 arguments (4 given) ошибку.

Функция открытия Python 3 — это то, что мне нужно. Могу ли я наследовать от этого? Я посмотрел на класс PyFile_FromFd, но ему нужен дескриптор открытого файла, и я обеспокоен тем, что поведение не будет таким же.

Спасибо!!!

Комментарии:

1. Вы уверены, что этот класс вообще еще нужен? Что create_string_buffer делает?

Ответ №1:

Вы не можете наследовать от open . Аргумент буферизации изменяет возвращаемый класс, поэтому open реализован как функция, которая может возвращать один из нескольких классов. Лучший вариант — сделать то же самое с вашими собственными классами-оболочками, если это необходимо.

Основная идея реализации заключается в:

  1. myfile является ли функция с сигнатурой, подобной open
  2. У вас есть два класса, один из которых наследуется от FileIO , другой от BufferedReader .
  3. При myfile вызове он проверяет buffering аргумент и либо создает и возвращает FileIO производный подкласс (если он небуферизован), либо создает обычный небуферизованный FileIO класс с open , затем переносит его в ваш BufferedReader производный подкласс.

Ответ №2:

Одним из быстрых решений было бы исправление обезьяны:

 def myfile(*args, **kwargs):
    f = open(*args, **kwargs)

    def read(size=-1):
        return create_string_buffer(f._read(size))

    f._read = f.read # save old read method
    f.read = read # patch

    return f