igal
igal

Reputation: 726

Python TemporaryDirectory returns string when used in "with" statement

Python TemporaryDirectory returns string when used in "with" statement

Short Version of Question

Why does TemporaryDirectory return a string when used in a with context?

Longer Version of Question

Here is an example of some Python code which creates a temporary directory tempdir and prints the corresponding object:

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

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

As expected, tempdir is an instance of TemporaryDirectory.

And here is a similar example, where I use a with statement when calling 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'>

In this case, tempdir is a string. When I look at the __enter__ method of the TemporaryDirectory class, I see the following:

def __enter__(self):
    return self.name

Sure enough - looks like a string is returned instead of the object itself.

What accounts for this discrepancy? Why does the __enter__ method return the file name instead of the file object?

Upvotes: 8

Views: 7301

Answers (2)

Adrian Shum
Adrian Shum

Reputation: 40056

Why does the enter method return the file name instead of the file object?

There is no discrepancy: tempfile.TemporaryDirectory is NOT a file object.

It is simply some kind of "context manager" to represent the context within the with-block, which wraps a str storing the path created by mkdtemp. There is nothing meaningful you can work with the TemporaryDirectory object but getting the name (for which __enter__ is returning) and cleanup (for which __exit__ is invoking)

Upvotes: -1

Grismar
Grismar

Reputation: 31354

From the source of tempfile.py, in the TemporaryDirectory class:

def __enter__(self):
    return self.name

As for the "why": The __enter__ and __exit__ methods control the behaviour of the class in a with block and apparently, the TemporaryDirectory class chooses to only give you the location - possibly to avoid tampering with the class and the cleanup afterwards. For example, calling .cleanup() before the end of the with block.

This would be undesirable:

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

And since TemporaryDirectory offers no other methods beyond that, I think the design decision makes sense, although the surprise for developers is a downside. Code should not be surprising, if it can be avoided.

Upvotes: 6

Related Questions