Python FileExistsError:[Errno 17]在文件上使用`open(“ ...”,“ r”)`(无mkdir)

时间:2019-04-08 02:32:50

标签: python file filesystems nfs strace

我遇到了一个奇怪的错误,很多人似乎是在完全不同的情况下发生的。在我发现的情况下,它主要与mkdir一起使用文件所在的路径被调用有关。

但就我而言,我只是在现有文本文件上调用open("meta.yml", "r")。堆栈跟踪明确指向仅调用open的行,具体来说

  File "some-path/experiment.py", line 348, in deserialize
    with open("meta.yml", "r") as f:
FileExistsError: [Errno 17] File exists: 'meta.yml'

函数本身很简单

def deserialize() -> "Experiment":
    with open("meta.yml", "r") as f:
        contents = f.read()
        obj = yaml.load(contents, Loader=yaml.Loader)

        # ...

并且错误发生在open调用的行上。

我非常确定文件存在,并且没有相同名称的目录。 需要注意的重要一点是,这不会在100%的时间内失败。我本质上是在循环中执行代码(中间有几秒钟的睡眠),这需要相当长的时间。同时发生例外。没有其他进程可以访问此文件,到目前为止,每次让它运行一段时间(例如一个小时),我都会失败(有时更快)。

我设法通过strace运行了故障,这是故障之前的最后几个电话

openat(AT_FDCWD, "/proc/37871/stat", O_RDONLY|O_CLOEXEC) = 4
fstat(4, {st_mode=S_IFREG|0444, st_size=0, ...}) = 0
ioctl(4, TCGETS, 0x7ffcabed25a0)        = -1 ENOTTY (Inappropriate ioctl for device)
lseek(4, 0, SEEK_CUR)                   = 0
lseek(4, 0, SEEK_CUR)                   = 0
fstat(4, {st_mode=S_IFREG|0444, st_size=0, ...}) = 0
read(4, "37871 (polkitd) S 1 37871 37871 "..., 8192) = 175
read(4, "", 8017)                       = 0
close(4)                                = 0
select(0, NULL, NULL, NULL, {tv_sec=1, tv_usec=0}) = 0 (Timeout)
openat(AT_FDCWD, ".lockfile", O_RDWR|O_CREAT|O_TRUNC|O_CLOEXEC, 0777) = 4
flock(4, LOCK_EX|LOCK_NB)               = 0
openat(AT_FDCWD, "meta.yml", O_RDONLY|O_CLOEXEC) = -1 EEXIST (File exists) # <- here it fails
flock(4, LOCK_UN)                       = 0
close(4)                                = 0

如您所见,openat返回带有句柄-1的EEXIST。有趣的是,在相同的跟踪中,在相同的系统调用成功返回之前发生了60次。这是一个例子

select(0, NULL, NULL, NULL, {tv_sec=1, tv_usec=0}) = 0 (Timeout)
openat(AT_FDCWD, ".lockfile", O_RDWR|O_CREAT|O_TRUNC|O_CLOEXEC, 0777) = 4
flock(4, LOCK_EX|LOCK_NB)               = 0
openat(AT_FDCWD, "meta.yml", O_RDONLY|O_CLOEXEC) = 5      # <- here it's ok
fstat(5, {st_mode=S_IFREG|0664, st_size=5194, ...}) = 0
ioctl(5, TCGETS, 0x7ffcabed2ec0)        = -1 ENOTTY (Inappropriate ioctl for device)
lseek(5, 0, SEEK_CUR)                   = 0
ioctl(5, TCGETS, 0x7ffcabed2ea0)        = -1 ENOTTY (Inappropriate ioctl for device)
lseek(5, 0, SEEK_CUR)                   = 0
lseek(5, 0, SEEK_CUR)                   = 0
fstat(5, {st_mode=S_IFREG|0664, st_size=5194, ...}) = 0
read(5, "gp_config: !!python/object:bopt."..., 5195) = 5194
read(5, "", 1)                          = 0
close(5)                                = 0

基于手册页,我不知道这怎么可能发生。可能值得注意的是,尽管文件只能从单个计算机上的单个进程访问,但它位于网络文件系统上。

0 个答案:

没有答案