如何在 Python 中的 Windows 上创建一个命名的临时文件?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2549384/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I create a named temporary file on windows in Python?
提问by Chris B.
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:
我有一个 Python 程序,它需要创建一个命名的临时文件,该文件将在程序运行过程中打开和关闭几次,并在程序退出时删除。不幸的是,tempfile
似乎没有一个选项有效:
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 settingdelete = 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 exits
TemporaryFile
没有可见的名字NamedTemporaryFile
创建一个类似文件的对象。我只需要一个文件名。我尝试关闭它返回的对象(设置后delete = False
),但是当我稍后尝试打开文件时出现流错误。SpooledTemporaryFile
没有可见的名字mkstemp
返回打开的文件对象和名称;它不保证在程序退出时删除文件mktemp
返回文件名,但不保证程序退出时删除文件
I've tried using mktemp
1within a context manager, like so:
我试过在上下文管理器中使用mktemp
1,如下所示:
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.
...但这给了我一个WindowsError(32, 'The process cannot access the file because it is being used by another process')
. 该文件名由我的程序生成的进程使用,即使我确保该进程在我退出之前完成,它似乎有一个我无法控制的竞争条件。
What's the best way of dealing with this?
处理这个问题的最佳方法是什么?
1I 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!
1我在这里不用担心安全问题;这是测试模块的一部分,因此不法之徒可能做的最多的事情就是导致我们的单元测试虚假失败。惊恐的事件!
回答by André Pang
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.
我今天需要类似的东西,最后写了我自己的。我正在使用 atexit.register() 注册一个函数回调,该回调在程序退出时删除文件。
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.
请注意,此编码标准与典型的 Python 编码标准(驼峰式而不是 using_underscores)略有不同。当然可以随意调整。
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()
回答by newtover
I have had exactly the same problem when I needed to save an uploaded file to the opened temporary file using the csv module. The most irritating thing was that the filename in WindowsError pointed to the temporary file, but saving the uploading file contents into the StringIO buffer and pushing the buffer data into the temporary file fixed the problem. For my needs that was enough since uploaded files always fit in memory.
当我需要使用 csv 模块将上传的文件保存到打开的临时文件时,我遇到了完全相同的问题。最烦人的是WindowsError中的文件名指向临时文件,但是将上传文件内容保存到StringIO缓冲区并将缓冲区数据推送到临时文件中解决了问题。对于我的需求,这已经足够了,因为上传的文件总是适合内存。
The problem was only when I uploaded a file with a script through Apache's CGI, when I ran the similar script from console I could not reproduce the problem though.
问题仅在于当我通过 Apache 的 CGI 上传带有脚本的文件时,当我从控制台运行类似的脚本时,我无法重现该问题。
回答by Hugues
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.
回答by jathanism
If you don't care about the security what is wrong with this?
如果你不关心安全,这有什么问题?
tmpfile_name = tempfile.mktemp()
# do stuff
os.unlink(tmpfile_name)
You might be trying to over-engineer this. If you want to make sure that this file is always removed when the program exits, you could wrap your main()
execution in a try/finally
. Keep it simple!
您可能试图对此进行过度设计。如果您想确保在程序退出时始终删除此文件,您可以将您的main()
执行包装在try/finally
. 把事情简单化!
if __name__ == '__main__':
try:
tmpfile_name = tempfile.mktemp()
main()
except Whatever:
# handle uncaught exception from main()
finally:
# remove temp file before exiting
os.unlink(tmpfile_name)