Как правильно закрыть файл, открытый классом? - PullRequest
0 голосов
/ 18 октября 2019

У меня есть класс, который я использую, чтобы отслеживать ход загрузки по FTP (используя ftplib).
Я использую ftplib с multiprocessing для загрузки нескольких файлов одновременно.
Это мой первыйпопытка использования класса в Python, и я сомневаюсь, закрываю ли я файл, который я открыл внутри класса. Ниже приведены фрагменты кода, которые, как мне кажется, подходят:

class track_transfer:
    def __init__(self, size, fname):
        self.file_name=fname
        self.size_in_bytes=size
        self.downloaded=0
        self.file=open(fname, 'wb')

    def __del__(self):
        try:
            self.file.close()
            self.file=None
        except:
            pass

    def update(self):
        self.downloaded=self.file.tell()
        if self.downloaded==self.size_in_bytes:
            self.file.close()

Как вы видите, я пытаюсь закрыть файлы в двух местах: один внутри финализатора, другой в методе класса update().
То, что я хотел знать, будет ли мой файл закрыт правильно, когда я использую этот класс?
Или есть лучший способ следовать?

ОБНОВЛЕНИЕ
Я думаю, что я могуздесь нужно предоставить больше информации.

Класс track_transfer имеет другой метод с именем progress (self, data) , определяемый следующим образом:

    def progress(self, data):
        self.file.write(data)
        self.update()

Создание экземпляра classAdded дополнительной информации,

tracker=track_transfer(size=fsize, fname=fname)

и загрузка файла,

ftp.retrbinary("RETR %s" %(fname),
        callback=tracker.progress)

, где ftp.retrbinary () - это метод, определенный в библиотеке ftplib получить файл как двоичный файл с FTP-сервера. Это вызовет метод tracker objetc progress при получении блока данных. Это означает, что метод progress () будет вызываться несколько раз при загрузке файла.

1 Ответ

1 голос
/ 18 октября 2019

__del__, вероятно, не помогает: он будет вызываться только тогда, когда экземпляр track_transfer будет собирать мусор, и, вероятно, это будет единственная вещь, которая имеет ссылку на файл - поэтому файл будет мусором-collected в любом случае, и Python закроет файл, когда этот объект будет сборщиком мусора. (__del__ для случаев очень специального назначения, с которыми вы, вероятно, не столкнетесь; Python - это, естественно, язык для сбора мусора, поэтому обычно мы не беспокоимся о таких вещах, как «деструкторы».)

Нормальный способдля управления временем жизни файлового объекта используется блок with:

with open(path, mode) as f:
    # do file operations
# file will be closed when the block is exited, even if by an exception etc.

Это работает, поскольку файл является собственным "диспетчером контекста" . Сохранение файла как атрибута класса не слишком хорошо сочетается с этим подходом, потому что вы хотите открыть файл одним вызовом метода класса и закрыть его в какой-то более поздний момент. Но мы можем исправить это, сделав наш класс менеджером контекста и используя его управление контекстом вместо файла.

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