The python docs for tempfile.NamedTemporaryFile
say:
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).
I have a program that's invoked as prog input.txt
, that I can't touch. I want to write a python function to give this a string.
Here's various approaches that don't quite work:
from tempfile import NamedTemporaryFile
Not obvious if legal on windows
with NamedTemporaryFile() as f:
f.write(contents)
subprocess.check_call(['prog', f.name]) # legal on windows?
Might delete the file too early
with NamedTemporaryFile() as f:
f.write(contents)
f.close() # does this delete the file?
subprocess.check_call(['prog', f.name])
Doesn't clean up properly
with NamedTemporaryFile(delete=False) as f:
f.write(contents) # if this fails, we never clean up!
try:
subprocess.check_call(['prog', f.name])
finally:
os.unlink(f.name)
A little ugly
f = NamedTemporaryFile(delete=False)
try:
with f:
f.write(contents)
subprocess.check_call(['prog', f.name])
finally:
os.unlink(f.name)
Which of these are correct?
As you suspected, the first three variants are all broken - the first one will throw a PermissionError
on Windows; the second one does indeed delete the file too early; and the third one doesn't handle exceptions properly.
Your fourth snippet is therefore the correct way to do it.
However, as you said, it is a little ugly. I suggest wrapping it in a function to improve readability and reusability:
import os
from contextlib import contextmanager
from tempfile import NamedTemporaryFile
@contextmanager
def ClosedNamedTempfile(contents, mode='w'):
f = NamedTemporaryFile(delete=False, mode=mode)
try:
with f:
f.write(contents)
yield f.name
finally:
os.unlink(f.name)
Which allows us to use it like so:
with ClosedNamedTempfile('foobar\n') as f:
subprocess.check_call(['prog', f])
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With