竞争条件Python中创建文件夹
-
22-09-2019 - |
题
我有一个urllib2的缓存模块,其偶尔崩溃由于以下代码:
if not os.path.exists(self.cache_location):
os.mkdir(self.cache_location)
的问题是,由正被执行的第二行的时候,该文件夹可以存在,并且将错误:
File ".../cache.py", line 103, in __init__ os.mkdir(self.cache_location) OSError: [Errno 17] File exists: '/tmp/examplecachedir/'
这是因为脚本是同步推出了无数次,通过第三方的代码,我在无法控制的。
代码(前我试图修复错误)可被这里找到,在github 一>
我不能使用 tempfile.mkstemp ,因为它解决了通过使用一个随机命名目录( tempfile.py源这里的竞争条件),它会破坏高速缓存的目的。
我不想简单地丢弃该错误,仿佛该文件夹名称存在作为文件(一个不同的错误),例如被升高的相同的错误errno的17错误:
$ touch blah $ python >>> import os >>> os.mkdir("blah") Traceback (most recent call last): File "", line 1, in OSError: [Errno 17] File exists: 'blah' >>>
我无法通过threading.RLock
作为代码从多个进程调用。
所以,我试图写一个简单的基于文件的锁(该版本可以是发现这里),但有一个问题:它创建了一个锁文件级别,所以/tmp/example.lock
为/tmp/example/
,如果你使用的休息作为高速缓存目录/tmp/
(因为它试图使/tmp.lock
)..
在短,我需要缓存urllib2
响应到光盘上。要做到这一点,我需要访问一个已知的目录(创建它,如果需要的话),在多进程安全的方式。这需要对OS X,Linux和Windows的工作。
思考?唯一的替代解决方案,我能想到的是使用的SQLite3存储,而不是文件重写高速缓存模块。
解决方案
在Python 3.x中,你可以使用os.makedirs(path, exists_ok=True)
,如果这样的目录存在,不会引发任何异常。如果文件具有相同的名称作为所请求的目录(FileExistsError: [Errno 17]
)存在,它会提高path
。
与验证:
import os
parent = os.path.dirname(__file__)
target = os.path.join(parent, 'target')
os.makedirs(target, exist_ok=True)
os.makedirs(target, exist_ok=True)
os.rmdir(target)
with open(target, 'w'):
pass
os.makedirs(target, exist_ok=True)
其他提示
代替
if not os.path.exists(self.cache_location):
os.mkdir(self.cache_location)
您可以做
try:
os.makedirs(self.cache_location)
except OSError:
pass
如你最终会使用相同的功能
<子>免责声明:我不知道如何Python的,这可能是
使用SQLite3
,的可能的是一个有点矫枉过正,但会增加的很多的功能性和灵活性,以你的使用情况。
如果您需要做大量的“选择”,并发插入和过滤的,这是一个伟大的想法,使用SQLite3
,因为它不会增加太多的复杂性比简单的文件(也可以说,它消除了复杂性)。
重读你的问题(和评论),我可以更好地了解您的问题。
什么是一个的文件可以创建相同的竞争条件的可能性?
如果它足够小,那么我会做这样的事情:
if not os.path.isfile(self.cache_location):
try:
os.makedirs(self.cache_location)
except OSError:
pass
此外,阅读你的代码,我会改变
else:
# Our target dir is already a file, or different error,
# relay the error!
raise OSError(e)
到
else:
# Our target dir is already a file, or different error,
# relay the error!
raise
,因为它真的是你想要的,Python来再加注完全相同的例外<子>(只是吹毛求疵)。
一两件事,可以是此可能是使用你(类Unix只)。
的我结束了的代码是:
import os
import errno
folder_location = "/tmp/example_dir"
try:
os.mkdir(folder_location)
except OSError as e:
if e.errno == errno.EEXIST and os.path.isdir(folder_location):
# File exists, and it's a directory,
# another process beat us to creating this dir, that's OK.
pass
else:
# Our target dir exists as a file, or different error,
# reraise the error!
raise
你能捕捉到了异常,然后测试该文件是否存在目录或不?
当你有竞争条件经常EAFP(更容易请求原谅比许可)的作品更好的是LBYL(三思而后行)