You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
tempfile.TemporaryDirectory() context manager can fail to propagate exceptions generated within its context #85034
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
assignee=Noneclosed_at=<Date2020-11-25.23:12:30.020>created_at=<Date2020-06-03.22:08:19.513>labels= ['3.7', 'type-bug', 'library']
title='tempfile.TemporaryDirectory() context manager can fail to propagate exceptions generated within its context'updated_at=<Date2020-11-25.23:12:30.018>user='https://bugs.python.org/granchester'
When an exception occurs within a tempfile.TemporaryDirectory() context
and the directory cleanup fails, the _cleanup exception_ is propagated,
not the original one. This effectively 'masks' the original exception,
and makes it impossible to catch using a simple 'try'/'except' construct.
----------------------------------------------------------------------------
Code like this:
importtempfileimportosimportsys
try:
with tempfile.TemporaryDirectory() as tempdir:
print(tempdir)
# some code happens here
is effective at catching any ArithmeticError which occurs in the
code fragment but is not otherwise handled. However if, in addition,
an error occues in cleaning up the temporary directory, the exception
which occurred in the code is replaced by the cleanup exception, and is
not be propagated to be caught by the 'except' clause.
For example:
importtempfileimportosimportsys
try:
with tempfile.TemporaryDirectory() as tempdir:
print(tempdir)
n = 1 / 0
/tmp/tmp_yz6zyfs
Traceback (most recent call last):
File "tempfilebug.py", line 9, in<module>
n =1/0
ZeroDivisionError: division by zero
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "tempfilebug.py", line 9, in<module>
n =1/0
File "/usr/lib/python3.6/tempfile.py", line 948, in__exit__self.cleanup()
File "/usr/lib/python3.6/tempfile.py", line 952, in cleanup
_rmtree(self.name)
File "/usr/lib/python3.6/shutil.py", line 477, in rmtree
onerror(os.lstat, path, sys.exc_info())
File "/usr/lib/python3.6/shutil.py", line 475, in rmtree
orig_st = os.lstat(path)
FileNotFoundError: [Errno 2] No such file or directory: '/tmp/tmp_yz6zyfs'
and the program exits with the top-level code having no chance to catch
the ZeroDivisionError and continue execution. (To catch this exception,
the top-level code would need to know to catch FileNotFoundError.)
My view is that if an exception happens within a TemporaryDirectory
context, *and* there is an exception generated as a result of the cleanup
process, the original exception is likely to be more significant, and
should be the exception which is propagated, not the one generated by
the cleanup.
----------------------------------------------------------------------------
System info:
$ python3 --version
Python 3.6.9
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 18.04.4 LTS
Release: 18.04
Codename: bionic
Activity
granchester commentedon Jun 3, 2020
When an exception occurs within a tempfile.TemporaryDirectory() context
and the directory cleanup fails, the _cleanup exception_ is propagated,
not the original one. This effectively 'masks' the original exception,
and makes it impossible to catch using a simple 'try'/'except' construct.
----------------------------------------------------------------------------
Code like this:
try:
with tempfile.TemporaryDirectory() as tempdir:
print(tempdir)
# some code happens here
is effective at catching any ArithmeticError which occurs in the
code fragment but is not otherwise handled. However if, in addition,
an error occues in cleaning up the temporary directory, the exception
which occurred in the code is replaced by the cleanup exception, and is
not be propagated to be caught by the 'except' clause.
For example:
try:
with tempfile.TemporaryDirectory() as tempdir:
print(tempdir)
n = 1 / 0
produces this:
/tmp/tmp_r2sxqgb
An arithmetic error occurred: division by zero
Continuing...
but this:
try:
with tempfile.TemporaryDirectory() as tempdir:
print(tempdir)
os.rmdir(tempdir) # this new line is the only difference
n = 1 / 0
produces this:
/tmp/tmp_yz6zyfs Traceback (most recent call last): File "tempfilebug.py", line 9, in <module> n = 1 / 0 ZeroDivisionError: division by zero During handling of the above exception, another exception occurred: Traceback (most recent call last): File "tempfilebug.py", line 9, in <module> n = 1 / 0 File "/usr/lib/python3.6/tempfile.py", line 948, in __exit__ self.cleanup() File "/usr/lib/python3.6/tempfile.py", line 952, in cleanup _rmtree(self.name) File "/usr/lib/python3.6/shutil.py", line 477, in rmtree onerror(os.lstat, path, sys.exc_info()) File "/usr/lib/python3.6/shutil.py", line 475, in rmtree orig_st = os.lstat(path) FileNotFoundError: [Errno 2] No such file or directory: '/tmp/tmp_yz6zyfs'and the program exits with the top-level code having no chance to catch
the ZeroDivisionError and continue execution. (To catch this exception,
the top-level code would need to know to catch FileNotFoundError.)
My view is that if an exception happens within a TemporaryDirectory
context, *and* there is an exception generated as a result of the cleanup
process, the original exception is likely to be more significant, and
should be the exception which is propagated, not the one generated by
the cleanup.
----------------------------------------------------------------------------
System info:
remilapeyre commentedon Jun 4, 2020
This was fixed in e9b51c0 so it's fixed in Python 3.8 and 3.9. Maybe it should have been backported to 3.7.
Python 3.6 only receives security fixes now.
See also bpo-26660 and bpo-35144.
iritkatriel commentedon Nov 25, 2020
Too late for 3.7 now, closing.