代码之家  ›  专栏  ›  技术社区  ›  Chris B.

如何用Python在windows上创建一个命名的临时文件?

  •  10
  • Chris B.  · 技术社区  · 15 年前

    我有一个Python程序,它需要创建一个命名的临时文件,这个文件在程序运行过程中会被打开和关闭几次,当程序退出时应该被删除。不幸的是,在 tempfile 似乎有效:

    • TemporaryFile 没有可见的名称
    • NamedTemporaryFile delete = False )但当我稍后尝试打开文件时,会出现流错误。
    • SpooledTemporaryFile 没有可见的名称
    • mkstemp 返回打开的文件对象和名称;它不保证程序退出时文件被删除
    • 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()
    

    WindowsError(32, 'The process cannot access the file because it is being used by another process') . 文件名由我的程序生成的进程使用,即使我确保进程在退出前完成,它似乎有一个竞争条件超出了我的控制。

    最好的办法是什么?

    1 我不需要担心这里的安全性;这是测试模块的一部分,所以nefarious能做的最多的事情就是导致我们的单元测试错误地失败。恐怖!

    3 回复  |  直到 15 年前
        1
  •  5
  •   André Pang    14 年前

    今天我需要类似的东西,最后我自己写了。我在用atexit.寄存器()注册一个函数回调,在程序退出时删除文件。

    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
    

    超基本测试代码:

    path = temporaryFilename(suffix='.log')
    print path
    writeFileObject = open(path, 'w')
    print >> writeFileObject, 'yay!'
    writeFileObject.close()
    
    readFileObject = open(path, 'r')
    print readFileObject.readlines()
    readFileObject.close()
    
        2
  •  2
  •   newtover    15 年前

    当我需要使用csv模块将上传的文件保存到打开的临时文件时,我遇到了完全相同的问题。最恼人的是WindowsError中的文件名指向临时文件,但将上载的文件内容保存到StringIO缓冲区并将缓冲区数据推送到临时文件中解决了问题。对于我的需要,这是足够的,因为上传的文件总是适合在内存中。

    问题只是当我通过Apache的CGI上传一个带有脚本的文件时,当我从控制台运行类似的脚本时,我无法重现这个问题。

        3
  •  1
  •   jathanism    15 年前

    如果你不关心安全,这有什么问题?

    tmpfile_name = tempfile.mktemp()
    # do stuff
    os.unlink(tmpfile_name)
    

    你可能想把这个设计得过火。如果要确保程序退出时始终删除此文件,可以包装 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)
    
        4
  •  1
  •   Hugues    5 年前

    创建一个临时目录,然后在该目录中创建一个静态文件名怎么样?目录和文件在退出上下文时被删除。

    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.