奇怪的竞争条件:带有mkdtemp的FileNotFoundError

时间:2014-03-25 15:30:17

标签: python race-condition temporary-directory

我在Mac OS X中使用Python获得了一个相当离奇的竞争条件(我只测试了Python 3.3)。我正在制作几个临时目录,向它们写东西,然后清除它们。

的内容
while running:
    (do something)
    tempdir = mkdtemp('name')
    try:
        (write some stuff to tempdir)
    finally:
        shutil.rmtree(tempdir)

但是,在(write some stuff to tempdir)的某些后续循环中,我会收到类似

的错误
    with open(os.path.join("/var/folders/yc/8wpl9rlx47qgzxqpcf003k280000gn/T/tmp0fh2ztname", "file"), 'w', encoding='utf-8') as fn:
FileNotFoundError: [Errno 2] No such file or directory: '/var/folders/yc/8wpl9rlx47qgzxqpcf003k280000gn/T/tmpups5dpname/file'

(为了清晰起见,我已将温度方向路径内联)

请注意,打开的路径与无法找到的路径不同。在每种情况下,错误消息中的路径都是上一次循环迭代的临时目录。

错误在大多数情况下可以在同一个地方重现(大约第四次迭代后),但不是每次都可以。

编辑:我刚刚意识到这可能是相关的。 (write some stuff to tempdir)内容实际上发生在子进程中。这就是我对tempdir路径的肯定,我必须将它传递给子进程(我实际上谎称“清晰度”位,我实际上是用精确的with open行写出一个Python文件)。这就是我确定tempdir路径确实与正在使用的路径不同的方式。

1 个答案:

答案 0 :(得分:2)

我明白了。事实证明它与mkdtemp无关(Mac OS X和Python在那里做正确的事情让人松了一口气)。

问题在于我将代码写入文件,包括with open(os.path.join("/var/folders/yc/8wpl9rlx47qgzxqpcf003k280000gn/T/tmp0fh2ztname", "file"), 'w', encoding='utf-8') as fn:位,并在子进程中运行它。问题是我每次都使用相同的文件,并且.pyc文件没有正确无效。

错误消息令人困惑,因为当Python生成回溯时,它会读取.py文件(实际代码所在的位置),但实际运行的是.pyc文件。

如果我正确理解http://nedbatchelder.com/blog/200804/the_structure_of_pyc_files.html,那么.pyc个文件中的时间戳就会有一秒的粒度(这就解释了为什么每次都可以在同一个地方重现:循环中相同的第四个项目是在一秒钟内。

解决方案是在写出文件时显式删除.pyc文件(在其他情况下,您也可以写出临时文件本身,但在我的情况下,我需要使用相同的名称导入文件)。

的内容
if sys.version_info >= (3,):
    os.unlink(os.path.join(path_to_file, '__pycache__', 'file.cpython-%s%s.pyc' % sys.version_info[:2]))
    os.unlink(os.path.join(path_to_file, '__pycache__', 'file.cpython-%s%s.pyo' % sys.version_info[:2]))
else:
    os.unlink(os.path.join(path_to_file, 'file.pyc'))
    os.unlink(os.path.join(path_to_file, 'file.pyo'))