Nat*_*man 5 python directory race-condition
我正在尝试将以下伪代码转换为 Python:
如果 <目录> 不存在:
为<目录>创建所有子目录
在 <目录> 中创建文件
os.makedirs这听起来很简单,可以用and来完成os.path.isdir:
if not os.path.isdir('/some/path'):
os.makedirs('/some/path')
open('/some/path/test.txt', 'w')
Run Code Online (Sandbox Code Playgroud)
然而,经过进一步检查,显然存在竞争条件。考虑以下时间表:
/some/path) 不存在True/some/path)makedirsOSError由于目录已存在而引发异常如果目录最初确实存在,但在执行最后一行之前被另一个进程删除,也会出现问题。
当谈到Python时,“请求原谅比请求许可更容易。” 考虑到这一点,上面的片段可以写得更好:
try:
os.makedirs('/some/path')
except OSError:
pass
open('/some/path/test.txt', 'w')
Run Code Online (Sandbox Code Playgroud)
这解决了上述两个问题,但产生了第三个问题:当发生以下情况之一时os.makedirs引发异常:OSError
这意味着无法确定这两个条件中的哪一个导致了引发异常。换句话说,实际的失败将被默默地忽略,这不是我想要的。
我该如何解决这个问题?
我会注意到,所有这些在 python 3 中都更加理智;FileExistsError和是您可以捕获的PermissionError单独( 的子类)异常,甚至当您对已经存在的目录感到满意时,甚至可以使用kwarg 来抑制前者。OSErroros.makedirsexist_ok
如果您想检查 的原因OSError,该信息位于元组中e.args(或者e.errno如果您只想查看错误代码,则可以选择):
try:
os.makedirs('/etc/python')
except OSError as e:
print e.args
(17, 'File exists')
try:
os.makedirs('/etc/stuff')
except OSError as e:
print e.args
(13, 'Permission denied')
try:
os.makedirs('/etc/stuff')
except OSError as e:
print e.errno
13
Run Code Online (Sandbox Code Playgroud)
因此,您必须进行一些内省,并在except块中以不同的方式处理两个错误代码。