Python получает WindowsError 5 при удалении файла, хотя у меня есть полные разрешения - PullRequest
0 голосов
/ 28 июня 2018

быстрый вопрос о Python на Windows. У меня есть сценарий, который компилирует программу (используя правило установки), а затем перемещает продукты сборки в удаленный пункт назначения по сети.

Тем не менее, я получаю WindowsError 5 Доступ запрещен. Все файлы создаются из контекста скрипта, я имею право собственности и полный контроль над ними. Копирование в удаленное место назначения успешно, но ошибка происходит во время процесса удаления. Если я пытаюсь удалить или переименовать файл вручную в Windows, я не получаю ошибок. Просто shutil.move терпит неудачу.

Я думаю, что, возможно, API пытается удалить файл, когда сетевая операция еще не завершена?

Любой вклад очень ценится.

try:
    shutil.move(directory, destination)
except OSError:
    print "Failed to move %s to %s." %(directory, destination)
    raise

...

Traceback (most recent call last):
  File "C:\WIP\BuildMachine\build_machine.py", line 176, in <module>
    main()
  File "C:\WIP\BuildMachine.hg\BuilderInstance.py", line 496, in deployVersion
    shutil.move(directory, destination)
  File "C:\Python27\lib\shutil.py", line 300, in move
    rmtree(src)
  File "C:\Python27\lib\shutil.py", line 252, in rmtree
    onerror(os.remove, fullname, sys.exc_info())
  File "C:\Python27\lib\shutil.py", line 250, in rmtree
    os.remove(fullname)
WindowsError: [Error 5] Access is denied: '3_54_7__B_1\\Application_Release_Note.doc'

1 Ответ

0 голосов
/ 28 июня 2018

проблема с shutil.move в Windows заключается в том, что он не обрабатывает случай, когда:

  • источник и место назначения не на одном диске И
  • некоторые файлы в исходном каталоге защищены от записи.

Если оба условия соблюдены, shutil.move не может выполнить os.rename, он должен:

  • скопировать файлы (что не проблема)
  • удалить исходные файлы (что является проблемой из-за ограничения shutil)

Чтобы исправить это, я сделал себе копию модуля shutil (под другим именем) и добавил эту строку (для вас это будет прямо перед строкой 250):

   os.chmod(fullname,0o777)  # <-- add that line
   os.remove(fullname)  # some versions have "unlink" instead

Функция rmtree имеет ту же проблему в Windows.

В Linux этого не происходит, поскольку разрешения на удаление файлов обрабатываются не на уровне файлов, а на уровне каталогов. На окнах это не работает таким образом. Добавление os.chmod делает свое дело (даже если это взлом), и os.remove успешно (если файл не открыт в Word или что-то еще)

Обратите внимание, что shutil авторы рекомендуют вам копировать и улучшать функции. Также примечание из документации shutil.move:

Здесь можно сделать гораздо больше ... Взгляд на mv.c показывает, что проблемы, которые затмевает эта реализация.

Если вы не хотите изменять shutil, вы можете запустить рекурсивный chmod для исходных файлов, чтобы убедиться, что shutil.move будет работать, например, так:

for root, dirs, files in os.walk(path):  
  for f in dirs+files:  
    os.chmod(os.path.join(root, f), 0o777)

Вы также можете использовать shutil.copytree, а затем модифицированную версию shutil.rmtree (поскольку вы знаете , что source & dest не находятся в одной файловой системе)

...