我的环境是在Windows 10上运行的Python 3.7.2。我正在使用目录选择小部件,并且正在寻找最干净,最确定的方法来测试所选目录路径是否允许写特权。 / p>
以前,我是通过通常的open()
方法打开一个命名文件的,向其中写入一些字节,然后删除它-将整个内容放入try-except
块中。没关系,但是有留下不需要的文件的风险。最近,我翻阅了tempfile.TemporaryFile()
的文档,这种似乎更干净的方法来获得相同的结果,而没有在系统上留下垃圾文件的风险。
问题是,当给tempfile.TemporaryFile()
一个只读文件夹的参数时,dir
挂在我的系统上。我在Google上四处搜寻,发现了this very old bug,但它是针对Python 2.4编写的,很久以前就已修复。
这是我拼凑来说明问题的测试脚本。 (请注意,我已经省略了实际应用程序执行的文件删除,因为它与插图无关。)
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)
当我运行此脚本时,它挂在最后一行上,然后坐在那里(任务管理器显示Python消耗约10-15%的CPU)。
有人知道这个问题可能是什么吗?特别是这是Python错误,还是我对TemporaryFile
的使用有问题?
如果有帮助,以下是Windows为这些文件夹显示的特定特权:
答案 0 :(得分:1)
比我最初做的更深入的潜水,找到了答案。这确实是a Python bug,它是在一段时间前报道的,但有待解决。
eryksun 的评论描述了细节-这就是促使我仔细研究Python错误数据库的原因-最终这才是我们应得的。我只是在这里填写它,以便回答并结束问题。
该错误仅影响Windows环境,但不幸的是,该错误导致tempfile.TemporaryFile
不能在Windows上用于此常见用例。
答案 1 :(得分:0)
我建议使用os.path.join(tempfile.gettempdir(), os.urandom(32).hex())
替换NamedTemporaryFile的用法。
这是更安全,更快和跨平台的。仅在FAT或DOS系统上失败,对于大多数人而言,这不再是问题。
这是兼容版本:
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)
..这是一个带有测试的模块:
https://gist.github.com/earonesty/a052ce176e99d5a659472d0dab6ea361