Временный каталог Python возвращает строку при использовании в инструкции «with»

#python #python-3.x

#python #python-3.x

Вопрос:

Временный каталог Python возвращает строку при использовании в инструкции «with»

Краткая версия вопроса

Почему TemporaryDirectory возвращает строку при использовании в with контексте?

Более длинная версия вопроса

Вот пример некоторого кода на Python, который создает временный каталог tempdir и печатает соответствующий объект:

 >>> import tempfile
>>> tempdir = tempfile.TemporaryDirectory(dir="/tmp")
>>> print(tempdir)
<TemporaryDirectory '/tmp/tmpf2yh8xu9'>

>>> print(type(tempdir))
<class 'tempfile.TemporaryDirectory'>
  

Как и ожидалось, tempdir является экземпляром TemporaryDirectory .

И вот аналогичный пример, где я использую with инструкцию при вызове TemporaryDirectory :

 >>> import tempfile
>>> with tempfile.TemporaryDirectory(dir="/tmp") as tempdir: print(tempdir)
/tmp/tmp7mlmzegs

>>> with tempfile.TemporaryDirectory(dir="/tmp") as tempdir: print(type(tempdir))
<class 'str'>
  

В этом случае tempdir является строкой. Когда я смотрю на __enter__ метод TemporaryDirectory класса, я вижу следующее:

 def __enter__(self):
    return self.name
  

Достаточно точно — похоже, что вместо самого объекта возвращается строка.

Чем объясняется это несоответствие? Почему __enter__ метод возвращает имя файла вместо объекта file?

Ответ №1:

Из источника tempfile.py , в TemporaryDirectory классе:

 def __enter__(self):
    return self.name
  

Что касается «почему»: Методы __enter__ и __exit__ управляют поведением класса в with блоке, и, по-видимому, TemporaryDirectory класс выбирает только указать вам местоположение — возможно, чтобы избежать вмешательства в класс и последующей очистки. Например, вызывается .cleanup() перед окончанием with блока.

Это было бы нежелательно:

 with TemporaryDirectory('/tmp') as td:
    td.cleanup()
  

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

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

1. Да, мой вопрос был неправильно сформулирован. Я фактически обновил свой вопрос, пока вы писали свой. Меня определенно интересует «почему».

2. Я думаю, что я высказал свое лучшее предположение о том, почему, которое я считаю справедливым, но я не уверен, что оно точное, могут быть дополнительные причины.

Ответ №2:

Почему метод enter возвращает имя файла вместо объекта file?

Несоответствия нет: tempfile.TemporaryDirectory не является файловым объектом.

Это просто своего рода «диспетчер контекста» для представления контекста внутри with -блока, который заключает в себе str сохранение пути, созданного mkdtemp . Нет ничего значимого, с чем вы могли бы работать с TemporaryDirectory объектом, кроме получения name (для которого __enter__ возвращается) и cleanup (для которого __exit__ выполняется вызов)

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

1. Определенно есть несоответствие между тем, что возвращается. TemporaryDirectory Класс не является str .

2. Вы пропустили суть: я упомянул: «это просто какой-то менеджер контекста». Без TemporaryDirectory вы должны были сделать d = mkdtemp() _shutil.rmtree(d) . Внутри этих двух строк вы просто работаете с, d который является str хранением пути. TemporaryDirectory просто завершает эти два действия для вас. Вот почему __enter__ возвращает str для вас, чтобы вы точно так же работали с результатом mkdtemp

3. tempfile.TemporaryDirectory is NOT a file object. Однако это так. Из документов Python: «Возвращает объект, подобный файлу. Где файлоподобный объект — синоним файлового объекта.». Так что это буквально файловый объект 🙂 docs.python.org/3/library/tempfile.html

4. @apatsekin то, что вы процитировали, находится под tempfile.TemporaryFile вместо tempfile.TemporaryDirectory , о чем говорится в документе: This function securely creates a temporary directory using the same rules as mkdtemp(). The resulting object can be used as a context manager... Так что это не файловый объект