#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.html4. @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...
Так что это не файловый объект