Python tempfile.TemporaryFile hangs on Windows when no write privilege

帅比萌擦擦* 提交于 2019-12-07 10:41:50

问题


My environment is Python 3.7.2, running on Windows 10. I'm working on a directory-selection widget, and I'm looking for the cleanest+surest method to test whether the selected directory path allows write privilege.

Previously I'd been opening a named file by the usual open() method, writing a few bytes to it, then deleting it -- putting the whole thing in a try-except block. This was OK but it ran the risk of leaving behind an unwanted file. Recently I came across the documentation for tempfile.TemporaryFile(), and this seemed cleaner way to get the same result, with no risk of leaving junk files on the system.

The problem is, tempfile.TemporaryFile() hangs on my system when it's given a dir parameter that's a read-only folder. I've googled around and found this very old bug, but it was written against Python 2.4 and was fixed long ago.

Here's a test script I put together to illustrate the issue. (Note that I've omitted the file-delete that my actual app performs, as it's not relevant for the illustration.)

import os, tempfile

def normOpen(checkPath):
    try:
        with open(os.path.join(checkPath,'x.txt'),'wb') as tf:
            tf.write(b'ABC')
    except Exception as e:
        print('Write disabled for '+checkPath)
        print(str(e))
    else:
        print('Write enabled  for '+checkPath)

def tfOpen(checkPath):
    try:
        with tempfile.TemporaryFile(dir=checkPath) as tf:
            tf.write(b'ABC')
    except Exception as e:
        print('Write disabled for '+checkPath)
        print(str(e))
    else:
        print('Write enabled  for '+checkPath)

tryPath1 = 'C:\\JDM\\Dev_Python\\TMPV\\canwrite'  #Full control path
tryPath2 = 'C:\\JDM\\Dev_Python\\TMPV\\nowrite'   #Read-only path

print('First method - normal file-open')
normOpen(tryPath1)
normOpen(tryPath2)

print('Second method - TemporaryFile')
tfOpen(tryPath1)
tfOpen(tryPath2)

When I run this script, it hangs on the last line and just sits there (Task Manager shows Python consuming about 10-15% CPU).

Does anyone know what the problem might be? Particularly is this a Python bug, or is there something wrong with my usage of TemporaryFile?

In case it helps, below is the specific privileges Windows shows for each of these folders:


回答1:


A deeper dive than I'd initially done, turned up the answer. This is indeed a Python bug, reported some time ago but which remains to be addressed.

The comments from eryksun describe the details -- and it's what prompted me to take a closer look at the Python bug database -- so ultimately that's where credit is due. I'm just filling it in here to get the question answered and closed out.

The bug affects only Windows environments, but unfortunately it has the result of rendering tempfile.TemporaryFile unusable on Windows for this common use case.




回答2:


I would suggest replacing usage of NamedTemporaryFile with os.path.join(tempfile.gettempdir(), os.urandom(32).hex()).

It's safer, faster, and cross-platform. Only fails on FAT or DOS systems, which isn't a problem for most people anymore.

Here's a compatible version:

import os, tempfile, gc


class TemporaryFile:
    def __init__(self, name, io, delete):
        self.name = name
        self.__io = io
        self.__delete = delete

    def __getattr__(self, k):
        return getattr(self.__io, k)

    def __del__(self):
        if self.__delete:
            os.unlink(self.name)


def NamedTemporaryFile(mode='w+b', bufsize=-1, suffix='', prefix='tmp', dir=None, delete=True):
    if not dir:
        dir = tempfile.gettempdir()
    name = os.path.join(dir, prefix + os.urandom(32).hex() + suffix)
    fh = open(name, "w+b", bufsize)
    if mode != "w+b":
        fh.close()
        fh = open(name, mode)
    return TemporaryFile(name, fh, delete)

..and here's a module with tests:

https://gist.github.com/earonesty/a052ce176e99d5a659472d0dab6ea361



来源:https://stackoverflow.com/questions/55109076/python-tempfile-temporaryfile-hangs-on-windows-when-no-write-privilege

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!