Python FileExistsError: [Errno 17] при использовании `open (" ... "," r ")` для файла (без mkdir) - PullRequest
0 голосов
/ 08 апреля 2019

Я сталкиваюсь со странной ошибкой, которая, похоже, возникает у многих людей в совершенно ином контексте.В случаях, которые я обнаружил, это в основном связано с вызовом 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)

        # ...

, и ошибка происходит в строке с opencall.

Я совершенно уверен, что и файл существует, и что нет каталога с таким именем. Важно отметить, что это не дает сбоя 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 возвращает EEXIST с дескриптором -1.Интересно то, что в одном и том же ряду есть 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

Основываясь на странице руководства, я не могу понять, как это могло произойти.Стоит отметить, что это происходит в сетевой файловой системе, хотя доступ к файлу возможен только из одного процесса на одном компьютере.

...