Hon*_*Abe 26 python race-condition
在确定文件是否存在时,如何使用try语句避免"竞争条件"?
我问,因为一个高度赞成的答案(更新:它被删除)似乎意味着使用os.path.exists()
创造了一个不存在的机会.
给出的例子是:
try:
with open(filename): pass
except IOError:
print 'Oh dear.'
Run Code Online (Sandbox Code Playgroud)
但我不明白如何避免竞争条件相比:
if not os.path.exists(filename):
print 'Oh dear.'
Run Code Online (Sandbox Code Playgroud)
如何调用os.path.exists(filename)
允许攻击者对他们不能做的文件做些什么?
Ell*_*ioh 32
当然,竞争条件是在您的程序和其他一些在文件上运行的代码之间(竞争条件总是需要至少两个并行进程或线程,详情请参阅此内容).这意味着使用open()
而不是exists()
仅仅在两种情况下可以帮助:
exists()
只需执行一次检查.如果文件存在,则exists()
返回后可能会删除一微秒True
.如果文件不存在,可以立即创建.
但是,open()
不仅测试文件存在,而且还打开文件(并以原子方式执行这两个操作,因此在检查和开放之间不会发生任何事情).通常,文件在某人打开时无法删除.这意味着with
你内心可能完全确定:文件现在确实存在,因为它是开放的.虽然它只在内部with
,但是在with
块退出后仍然可以立即删除文件,将需要文件的代码放在内部可以with
保证代码不会失败.
这是一个用法示例:
try:
with open('filename') as f:
do_stuff_that_depends_on_the_existence_of_the_file(f)
except IOError as e:
print 'Trouble opening file'
Run Code Online (Sandbox Code Playgroud)
如果您打开任何访问权限的文件,那么操作系统将保证该文件存在,否则它将失败并显示错误.如果访问权限是独占的,则任何其他争用文件的进程都将被您阻止,或阻止您.
这try
只是一种检测打开文件的错误或成功的方法,因为Python中的文件I/O API通常没有返回代码(而是使用异常).所以要真正回答你的问题,那不是try
避免竞争条件,而是它open
.它在C(Python所基于的)中基本相同,但没有例外.阅读本文以获取更多信息.
请注意,您可能希望执行依赖于对try块内文件的访问的代码.关闭文件后,不再保证其存在.
调用os.path.exists
仅在文件可能存在或不存在的时刻给出快照,并且一旦os.path.exists
返回就不知道文件是否存在.恶意代码或意外逻辑可能会在您不期望时删除或更改文件.它类似于在开车前检查道路是否清晰.一旦你转过头来,你只能猜测你不再寻找的地方.保持文件打开可确保延长的一致状态,这在驾驶时是不可能的(无论好坏).:)
try/open
由于快照性质的原因,您建议检查文件是否存在而不是使用仍然是不够的os.path.exists
.不幸的是,我知道在所有情况下都无法阻止在目录中创建文件,因此我认为最好检查文件是否存在,而不是缺少文件.