os.path.exists()谎言

时间:2010-06-24 17:48:19

标签: python

我在linux集群上运行了许多python脚本,一个作业的输出通常是另一个脚本的输入,可能在另一个节点上运行。我发现在其他节点上创建的python通知文件之前有一些不显着的滞后 - os.path.exists()返回false,而open()也失败。我可以做一段时间而不是os.path.exists(mypath)循环,直到文件出现,并且它可能需要花费整整一分钟,这在具有许多步骤并且可能并行运行许多数据集的管道中不是最佳的。

到目前为止,我发现的唯一解决方法是调用subprocess.Popen(“ls%s”%(pathdir),shell = True),这会神奇地解决问题。我认为这可能是一个系统问题,但是python可能导致这种情况的任何方式?某种缓存还是什么?到目前为止,我的系统管理员帮助不大。

2 个答案:

答案 0 :(得分:10)

os.path.exists()只调用C库的stat()函数。

我相信你在内核的NFS实现中遇到了缓存。下面是描述问题的页面的链接以及刷新缓存的一些方法。

  

文件句柄缓存

     

目录将文件名缓存到文件句柄映射。最常见的问题是:

     

•您有一个打开的文件,您需要检查该文件是否已被更新的文件替换。在stat()返回新文件的信息而不是打开的文件之前,您必须刷新父目录的文件句柄缓存。

     

◦实际上这种情况还有另一个问题:旧文件可能已被删除并被新文件替换,但这两个文件可能具有相同的inode。您可以通过刷新打开文件的属性缓存来检查这种情况,然后查看fstat()是否因ESTALE而失败。

     

•您需要检查文件是否存在。例如一个锁文件。内核可能已缓存该文件不存在,即使实际上它也存在。您必须刷新父目录的负文件句柄缓存以查看该文件是否确实存在。

     

一些刷新文件句柄缓存的方法:

     

•如果父目录的mtime发生更改,则通过刷新其属性缓存来刷新文件句柄缓存。如果NFS服务器支持纳秒或微秒分辨率,这应该可以很好地工作。

     

•Linux:chown()将当前所有者的目录。如果调用成功返回,则刷新文件句柄缓存。

     

•Solaris 9,10:唯一的方法是尝试使用rmdir()父目录。 ENOTEMPTY表示刷新缓存。尝试rmdir()当前目录失败并使用EINVAL并且不刷新缓存。

     

•FreeBSD 6.2:唯一的方法是尝试使用rmdir()父目录或其下的文件。 ENOTEMPTY,ENOTDIR和EACCES失败意味着刷新缓存,但ENOENT没有刷新它。 FreeBSD不会缓存否定条目,因此不必刷新它们。

http://web.archive.org/web/20100912144722/http://www.unixcoding.org/NFSCoding

答案 1 :(得分:1)

问题与Python进程在自己的shell中运行有关。当您运行subprocess.Popen(shell=True)时,您将生成一个新的shell,这正在解决您遇到的问题。

Python不会导致此问题。它是NFS(文件存储)和目录列表在Linux中的运行方式的组合。

相关问题