Sometimes, one creates a file that should be persisted somewhere, but only after lots of work and/or sanity checks. For that, it would be useful to be able to create a tempfile.NamedTemporaryFile with the default delete=True, but then, once all the work is done and the file is to be kept, one should be able to do
os.rename(f.name, final_location)
f.set_delete(False) # this
f.close()
In fact, since the object one gets from the NamedTemporaryFile() call has a .delete property, one is easily led to believe that it’s possible to modify that with the expected result, in the same way that .name is a public property. But the current implementation copies the delete flag to the closer helper object, and obviously user code should not do f._closer.delete = False.
So I’d like to have either a set_delete() method on the _TemporaryFileWrapper object, or alternatively that assigning directly to its .delete property should have the expected effect.
Perl’s corresponding File::Temp provides this via an ->unlink_on_destroy method.
Is that still true if the temporary file is used as a context manager (as it should be imo)? You’d have to wrap it all in a careful try-except, which seems error prone.
import tempfile
import os
import time
import shutil
# Create a temporary file with delete=False
with tempfile.NamedTemporaryFile(delete=False) as temp_file:
# Do some operations with the temporary file
temp_file.write(b"Hello, World!")
temp_file.seek(0)
data = temp_file.read()
print("Data from temporary file:", data)
print("Temporary file path:", temp_file.name)
time.sleep(10.0)
# Copy file
shutil.copy(temp_file.name, 'tmp_file')
# Delete the temporary file manually when you're done with it
os.remove(temp_file.name)
In my opinion, it’s better for all bracketing patterns to be context managers. Otherwise, as in your code, if copy raises an exception, then the file won’t be deleted.
My experience has led me to always implement the following workflow:
Create a temporary directory (using TemporaryDirectory context manager) on at least the same mount as the intended final location (easiest choice is the same directory as the intended final location but not always possible for some workflows)
Create the file with the same name as the intended final name inside the temporary directory
Do any work required
If keeping the file move it to the correct directory
If not keeping the file do not move
Let the context manager exit, so the temporary directory and any of it’s contents are cleaned up
Personally I have found this works well regardless of platform.