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: NamedTemporaryFile opened twice on Windows
Type: enhancement Stage:
Components: Documentation, Windows Versions: Python 3.8
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: docs@python Nosy List: docs@python, eryksun, frenzy, paul.moore, steve.dower, tim.golden, zach.ware
Priority: normal Keywords:

Created on 2021-05-06 10:47 by frenzy, last changed 2022-04-11 14:59 by admin.

Messages (3)
msg393082 - (view) Author: Lumír Balhar (frenzy) * Date: 2021-05-06 10:47
Hello.

The documentation about tempfile.NamedTemporaryFile[0] contains:

That name can be retrieved from the name attribute of the returned file-like object. Whether the name can be used to open the file a second time, while the named temporary file is still open, varies across platforms (it can be so used on Unix; it cannot on Windows NT or later).

But after some testing on Windows, it seems that there is no problem in opening a temporary file for the second time. A simple reproducer:

from tempfile import NamedTemporaryFile
​
# Open the file for the first time
tmp_file = NamedTemporaryFile(mode="w+", delete=False)
tmp_file.write("foo")
tmp_file.seek(0)
content_original = tmp_file.read()
print("Original content:", content_original)
​
# Open the file for the second time
with open(tmp_file.name, mode="w+") as file:
    file.write("bar")
    file.seek(0)
    content = file.read()
    print("Updated content:", content)

The output is:

Original content: foo
Updated content: bar

So the question is: do I misunderstand the documentation? Or is there any automatic magic handling this on Windows?

I'm not a windows user and I've found this accidentally when preparing a Windows CI job for a project.

[0] https://docs.python.org/3/library/tempfile.html?highlight=namedtemporaryfile#tempfile.NamedTemporaryFile
msg393112 - (view) Author: Eryk Sun (eryksun) * (Python triager) Date: 2021-05-06 17:06
Your example uses delete=False. In Windows, the provision about reopening the file while it's open applies to delete=True. With the latter, the file is opened with the O_TEMPORARY flag. At the OS level, this flag modifies the CreateFileW() call as follows:

     dwDesiredAccess |= DELETE; 
     dwShareMode |= FILE_SHARE_DELETE; 
     dwFlagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE;

Because the open has delete access, which it shares, it can be opened again only if the open shares delete access. An open that doesn't share delete access will fail with a sharing violation. It can be reopened with os.open() with the O_TEMPORARY flag, since this shares delete access. But Python's builtin open() does not share delete access, and neither do most other programs with which one might want to reopen the file. 

This behavior is limiting to the point of making NamedTemporaryFile() practically useless in Windows with delete=True. There is an ongoing discussion about redesigning NamedTemporaryFile() to never use O_TEMPORARY in Windows.
msg393369 - (view) Author: Lumír Balhar (frenzy) * Date: 2021-05-10 09:20
I understand, thanks for the explanation.

I'd like to improve the documentation to make it more clear that the file actually can be reopened on Windows when you use delete=False but I cannot find the right words :/

What about:

That name can be retrieved from the name attribute of the returned file-like object. If delete is true (the default), the file is deleted as soon as it is closed. Whether the name can be used to open the file a second time, while the named temporary file is still open with delete set to true, varies across platforms (it can be so used on Unix; it cannot on Windows NT or later).
History
Date User Action Args
2022-04-11 14:59:45adminsetgithub: 88221
2021-05-10 09:20:28frenzysetmessages: + msg393369
2021-05-06 17:06:35eryksunsettype: enhancement

messages: + msg393112
nosy: + eryksun
2021-05-06 10:47:41frenzycreate