I've got a Python program that needs to create a named temporary file which will be opened and closed a couple times over the course of the program, and should be deleted when the program exits. Unfortunately, none of the options in tempfile
seem to work:
TemporaryFile
doesn't have a visible nameNamedTemporaryFile
creates a file-like object. I just need a filename. I've tried closing the object it returns (after setting delete = False
) but I get stream errors when I try to open the file later.SpooledTemporaryFile
doesn't have a visible namemkstemp
returns both the open file object and the name; it doesn't guarantee the file is deleted when the program exitsmktemp
returns the filename, but doesn't guarantee the file is deleted when the program exitsI've tried using mktemp
1 within a context manager, like so:
def get_temp_file(suffix):
class TempFile(object):
def __init__(self):
self.name = tempfile.mktemp(suffix = '.test')
def __enter__(self):
return self
def __exit__(self, ex_type, ex_value, ex_tb):
if os.path.exists(self.name):
try:
os.remove(self.name)
except:
print sys.exc_info()
return TempFile()
... but that gives me a WindowsError(32, 'The process cannot access the file because it is being used by another process')
. The filename is used by a process my program spawns, and even though I ensure that process finishes before I exit, it seems to have a race condition out of my control.
What's the best way of dealing with this?
1 I don't need to worry about security here; this is part of a testing module, so the most someone nefarious could do is cause our unit tests to spuriously fail. The horror!
The tempfile module in standard library defines functions for creating temporary files and directories. They are created in special temp directories that are defined by operating system file systems.
Temporary files, also called temp or tmp files, are created by Windows or programs on your computer to hold data while a permanent file is being written or updated. The data will be transferred to a permanent file when the task is complete, or when the program is closed.
How about creating a temporary directory and then a static filename within that directory? The directory and the file are removed upon exit from the context.
with tempfile.TemporaryDirectory() as directory_name:
filename = os.path.join(directory_name, 'file' + suffix)
# use the filename to open a file for writing, or run a os.system() command, etc.
I needed something similar to this today, and ended up writing my own. I'm using atexit.register() to register a function callback that removes the file when the program exits.
Note that the coding standards for this are slightly different from the typical Python coding standards (camelCase rather than using_underscores). Adjust at will, of course.
def temporaryFilename(prefix=None, suffix='tmp', dir=None, text=False, removeOnExit=True):
"""Returns a temporary filename that, like mkstemp(3), will be secure in
its creation. The file will be closed immediately after it's created, so
you are expected to open it afterwards to do what you wish. The file
will be removed on exit unless you pass removeOnExit=False. (You'd think
that amongst the myriad of methods in the tempfile module, there'd be
something like this, right? Nope.)"""
if prefix is None:
prefix = "%s_%d_" % (os.path.basename(sys.argv[0]), os.getpid())
(fileHandle, path) = tempfile.mkstemp(prefix=prefix, suffix=suffix, dir=dir, text=text)
os.close(fileHandle)
def removeFile(path):
os.remove(path)
logging.debug('temporaryFilename: rm -f %s' % path)
if removeOnExit:
atexit.register(removeFile, path)
return path
Super-basic test code:
path = temporaryFilename(suffix='.log')
print path
writeFileObject = open(path, 'w')
print >> writeFileObject, 'yay!'
writeFileObject.close()
readFileObject = open(path, 'r')
print readFileObject.readlines()
readFileObject.close()
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