os.path.join обращается к файлу, предотвращающему операцию переименования - PullRequest
0 голосов
/ 13 мая 2019

Я пытаюсь обработать JSON-декодирование путем резервного копирования искаженного файла при сбое декодирования, но я испытываю странное поведение, которого я не ожидал от метода os.path.join.

Сбой следующего кода за исключением: PermissionError: [WinError 32] The process cannot access the file because it is being used by another process: 'file.txt' -> 'file.txt\\.bak'

file_path = "file.txt"

try:
    with open(file_path, 'r') as f:
        json.load(f)

except json.JSONDecodeError as e:
    os.rename(file_path, os.path.join(file_path, '.bak'))

Если я изменю аргумент следующим образом: os.rename(file_path, file_path + '.bak') Код выполняется должным образом без ошибки разрешения. Кажется, что метод os.path.join на самом деле обращается к файлу, а не является строгой строковой операцией. Это ожидаемое поведение?

Ответы [ 2 ]

1 голос
/ 13 мая 2019

Сообщение об ошибке является ключом.Как обычно в Windows, причина (, потому что она используется другим процессом ) неверна, но имена ( 'file.txt' -> 'file.txt \ .bak' ) являются правильными.

Присоединение не является конкатенацией строк, но предполагает, что все элементы пути, кроме последнего, представляют папки.Итак, здесь вы пытаетесь создать файл .bak в папке с именем file.txt.Это невозможно, потому что file.txt - это простой файл, а не каталог.

С другой стороны, когда вы используете os.rename(file_path, file_path + '.bak'), вы переименовываете file.txt в file.txt.bak в той же папке, которая разрешенаосновной файловой системой, следовательно, ошибки нет.

Таким образом, поведение соответствует ожидаемому, за исключением начала сообщения об ошибке.


Поскольку я не являюсь основным MicrosoftДевелоппер, следующее - это дикая догадка.Количество ошибок, указанных системой, ограничено.Функция переименования C получила 2 строки и передала их системному вызову для переименования.Как и ожидалось, файловая система вызвала ошибку, но так как она не была ни физической, ни полной ошибкой файловой системы, она просто выбрала отказано в разрешении причина.Что на самом деле не так, потому что не разрешено создавать папки в виде простого файла.Но сообщение об этой ошибке, к сожалению, , потому что оно используется другим процессом , что здесь глупо

1 голос
/ 13 мая 2019

os.path.join(file_path, '.bak')) на самом деле даст вам file.txt\\.bak, как вы видите в коде ошибки, но file_path + '.bak' даст вам правильное имя файла file.txt.bak

os.path.join добавляет разделитель между своими аргументами, следовательно, в конечном итоге он добавляет этот разделитель и в вашем случае

Пример в MacOS, вы можете видеть, что он добавляет разделитель между каждым из своих аргументов.os.path.join более полезен для добавления имен каталогов, полного имени файла с путями к каталогам.

In [4]: import os                                                                                                                                                                 

In [5]: os.path.join('filename','.bak')                                                                                                                                           
Out[5]: 'filename/.bak'

In [6]: os.path.join('folder1', 'folder2')                                                                                                                                        
Out[6]: 'folder1/folder2'

Ошибка возникает, поскольку ОС Windows пытается создать файл .bak в папке.с именем file.txt, что невозможно, поскольку file.txt является простым файлом, а не каталогом, что является правильным.

Использование file_path+'.bak создает file.path.bak правильно в нужной папке, следовательно,вы не видите там ошибки!

...