This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: tempfile seems to treat a file as a directory when processing an exception in the onerror()
Type: behavior Stage: patch review
Components: Library (Lib) Versions: Python 3.11, Python 3.10, Python 3.9
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: andrei.avk, kj, mehwhatever0, serhiy.storchaka
Priority: normal Keywords: patch

Created on 2021-02-07 09:52 by mehwhatever0, last changed 2022-04-11 14:59 by admin.

Pull Requests
URL Status Linked Edit
PR 29940 open kj, 2021-12-06 14:13
Messages (4)
msg386587 - (view) Author: Oleg Navolotsky (mehwhatever0) Date: 2021-02-07 09:52
>>> import sys, tempfile, os
>>> sys.version
'3.9.1 (tags/v3.9.1:1e5d33e, Dec  7 2020, 17:08:21) [MSC v.1927 64 bit (AMD64)]'
>>> folder = tempfile.TemporaryDirectory()
>>> file = open(os.path.join(folder.name, "example.txt"), 'wb')
>>> folder.cleanup()
Traceback (most recent call last):
  File "C:\Users\user0\AppData\Local\Programs\Python\Python39\lib\shutil.py", line 616, in _rmtree_unsafe
    os.unlink(fullname)
PermissionError: [WinError 32] Процесс не может получить доступ к файлу, так как этот файл занят другим процессом: 'C:\\Users\\user0\\AppData\\Local\\Temp\\tmpin8xeb9b\\example.txt'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\user0\AppData\Local\Programs\Python\Python39\lib\tempfile.py", line 801, in onerror
    _os.unlink(path)
PermissionError: [WinError 32] Процесс не может получить доступ к файлу, так как этот файл занят другим процессом: 'C:\\Users\\user0\\AppData\\Local\\Temp\\tmpin8xeb9b\\example.txt'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\user0\AppData\Local\Programs\Python\Python39\lib\tempfile.py", line 830, in cleanup
    self._rmtree(self.name)
  File "C:\Users\user0\AppData\Local\Programs\Python\Python39\lib\tempfile.py", line 812, in _rmtree
    _shutil.rmtree(name, onerror=onerror)
  File "C:\Users\user0\AppData\Local\Programs\Python\Python39\lib\shutil.py", line 740, in rmtree
    return _rmtree_unsafe(path, onerror)
  File "C:\Users\user0\AppData\Local\Programs\Python\Python39\lib\shutil.py", line 618, in _rmtree_unsafe
    onerror(os.unlink, fullname, sys.exc_info())
  File "C:\Users\user0\AppData\Local\Programs\Python\Python39\lib\tempfile.py", line 804, in onerror
    cls._rmtree(path)
  File "C:\Users\user0\AppData\Local\Programs\Python\Python39\lib\tempfile.py", line 812, in _rmtree
    _shutil.rmtree(name, onerror=onerror)
  File "C:\Users\user0\AppData\Local\Programs\Python\Python39\lib\shutil.py", line 740, in rmtree
    return _rmtree_unsafe(path, onerror)
  File "C:\Users\user0\AppData\Local\Programs\Python\Python39\lib\shutil.py", line 599, in _rmtree_unsafe
    onerror(os.scandir, path, sys.exc_info())
  File "C:\Users\user0\AppData\Local\Programs\Python\Python39\lib\shutil.py", line 596, in _rmtree_unsafe
    with os.scandir(path) as scandir_it:
NotADirectoryError: [WinError 267] Неверно задано имя папки: 'C:\\Users\\user0\\AppData\\Local\\Temp\\tmpin8xeb9b\\example.txt'
msg397118 - (view) Author: Andrei Kulakov (andrei.avk) * (Python triager) Date: 2021-07-07 21:17
This is a duplicate of https://bugs.python.org/issue43219 .
msg407376 - (view) Author: Andrei Kulakov (andrei.avk) * (Python triager) Date: 2021-11-30 14:36
My last comment was wrong, the issue I linked is unrelated.

I think the actual issue here is the code here:
https://github.com/python/cpython/blob/4b97d974ecca9cce532be55410fe851eb9fdcf21/Lib/tempfile.py#L826

If `path` is a file that causes a permission error, `rmtree` is called and causes a NotADirectory error.

This can be confusing when debugging and can lead to a bug if user's code tries to catch a PermissionError it expects but instead gets NotADirectory error.

A solution is probably to check if path is a file and error is PermissionError and if ignore_errors=False, re-raise it instead of calling rmtree(). If ignore_errors=True, return instead of calling rmtree().

I don't have windows so can't test the OP code with this approach.

Serhiy: adding you since you wrote `def onerror()` in tempfile module, do you think that is the cause of the issue and the right solution for it?
msg407435 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2021-12-01 09:59
I agree with Andrei. I'll test this approach on Windows.
History
Date User Action Args
2022-04-11 14:59:41adminsetgithub: 87319
2021-12-06 14:13:37kjsetkeywords: + patch
stage: patch review
pull_requests: + pull_request28165
2021-12-01 09:59:22serhiy.storchakasetmessages: + msg407435
2021-11-30 14:36:02andrei.avksetnosy: + serhiy.storchaka, kj
messages: + msg407376
2021-07-07 21:17:40andrei.avksetnosy: + andrei.avk

messages: + msg397118
versions: + Python 3.10, Python 3.11
2021-02-07 09:52:44mehwhatever0create