我在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路径确实与正在使用的路径不同的方式。
答案 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'))