一尘不染

使用try语句如何避免出现竞争情况?

python

在确定文件是否存在时,使用try语句如何避免“竞争条件”?

我之所以这样问是因为高度支持的答案0)(更新:已删除)似乎暗示使用os.path.exists()会创造机会,否则这种机会就不会存在。

给出的示例是:

try:
   with open(filename): pass
except IOError:
   print 'Oh dear.'

但与以下内容相比,我不了解如何避免出现竞争状况:

if not os.path.exists(filename):
    print 'Oh dear.'

调用如何os.path.exists(filename)使攻击者能够处理他们无法完成的文件?


阅读 132

收藏
2020-12-20

共1个答案

一尘不染

比赛条件,当然,你的程序和文件上运行一些其他的代码之间(竞争状态总是需要至少两个平行的进程或线程,看到这个细节)。这意味着仅在以下两种情况下使用open()而不是exists()可能真正有用:

  1. 您检查是否存在由某些后台进程创建或删除的文件(但是,如果您在Web服务器中运行,则通常意味着您的进程有很多副本并行运行以处理HTTP请求,因此对于Web应用程序来说,即使没有其他程序,也可能出现这种情况)。
  2. 可能有一些正在运行的恶意程序正在尝试通过在您希望文件存在的时刻破坏文件来破坏您的代码。

exists()只需执行一次检查。如果文件存在,则可以在exists()返回后一微秒内将其删除True。如果没有文件,则可以立即创建。

但是,open()不仅要测试文件是否存在,还要打开文件(并且自动执行这两个操作,因此在检查和打开之间不会发生任何事情)。通常,当有人打开文件时,无法将其删除。这意味着with您可能会完全确定:由于文件已打开,因此它现在确实存在。尽管只有在内部才是正确的with,并且在with块退出后仍可能会立即删除文件,但是将需要文件存在的with代码放入其中可以确保代码不会失败。

2020-12-20