2

我在使用 Python 的 Mac OS X 中遇到了一个相当奇怪的竞争条件(我只测试了 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'

(为了清楚起见,我已经内联了 temp dir 路径)

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

该错误大部分时间在同一个地方(大约第四次迭代之后)是可重现的,但不是每次都可以重现。

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

4

1 回答 1

3

我想到了。事实证明它与 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'))
于 2014-03-25T16:24:45.780 回答