Python ftplib: как правильно освободить объект подключения?

Я видел такой код (код Python 3):

import ftplib
from contextlib import closing

with closing(ftplib.FTP()) as ftp:

Является ли использование closing метод нужен? В интересном ответе мы можем прочитать, что в объектах соединения с базой данных менеджер контекста __exit__ Метод не закрывает соединение (по крайней мере, для SQLite), но вместо этого фиксирует транзакцию. Поэтому, используя closing метод необходим.

Как это с классом FTP Python?

Глядя на исходники ftplib Python, мы можем найти это:

# Context management protocol: try to quit() if active
def __exit__(self, *args):
    if self.sock is not None:
        try:
            self.quit()
        except (OSError, EOFError):
            pass
        finally:
            if self.sock is not None:
                self.close()

quit метод называется, следовательно, я думаю, что мы не должны использовать closing метод для Python 3. Таким образом, мы можем использовать только:

with (ftplib.FTP()) as ftp:

поскольку __exit__ метод отсутствует в Python 2, closing необходим для кода Python 2.

Это правильно?

1 ответ

Решение

Вы ответили на свой вопрос по большей части.
И, как обсуждалось в комментариях, это законный вопрос, так как Интернет "завален неправильными примерами кода".

Чтобы прояснить мой короткий ответ, это проблема наследия, когда код Python3 не работает должным образом на Python2. Так что (хорошие) примеры в интернете, мы надеемся, будут либо содержать объяснение опасности запуска кода в Python2... Или они сделают код обратно совместимым с небольшой модификацией.

Это такой случай, когда closing() используется для эмуляции новых функций из Python3, когда код выполняется на Python2.

Python2 (ftplib) не имеет ни __enter__ или __exit__ функция, что делает дескриптор контекста "бесполезным" (за исключением того, что делает его совместимым с форвардом, более легким для чтения IMO, а также назначает вызов переменной, в данном случае ftp).
Чтобы сделать его бесполезным, писатель использовал closing() вокруг вызова, чтобы получить автоматическое закрытие в соответствии с Python3.

Если вы используете Python3, это избыточно и, вероятно, замедляет ваш код (крайне мало). И там вы можете пропустить этот конкретный кусок кода, если вы не хотите иметь обратную совместимость.

Другие вопросы по тегам