#python #python-3.x #path #pathlib
#python #python-3.x #путь #pathlib
Вопрос:
Я пытаюсь вернуть список всех файлов и вложенных папок в определенном месте. Мой код выглядит следующим образом:
from pathlib import Path
FOLDER_PATH = Path(r'C:longfilepathof138characters')
Я получаю ошибку:
FileNotFoundError: [WinError 3] The system cannot find the path specified:
Ошибка возникает в пути к папке, а не в файле, поэтому я не уверен, может ли это быть причиной.
Когда я захожу в папку вручную и пытаюсь открыть PDF
там, я получаю «Произошла ошибка при открытии этого документа. Этот файл не может быть найден.»
Аналогично, когда я пытаюсь открыть XLSX
файл, я получаю сообщение «К этому файлу невозможно получить доступ. Попробуйте одно из следующих действий: (убедитесь, что оно существует, не доступно только для чтения, не превышает 218 символов и т.д.)»
Пути к файлам в этой папке, безусловно, содержат более 218 символов, что, как я понимаю, может быть проблемой для Excel, но я не понимаю, почему это было бы проблемой для pathlib.Path.rglob
их перечисления, кто-нибудь это понимает?
Однако, если я использую CMD
( dir /s /b > files.txt
), я могу получить список.
Кроме того, если я затем импортирую files.txt
в список Path
объектов paths
на python и попытаюсь выполнить [x.is_file() for x in paths]
, он не будет правильно идентифицировать некоторые из более длинных путей как файлы.
Я проверил, что если я скопирую каталог локально (где существует гораздо более короткий путь), то файлы будут доступны с помощью Excel и pathlib.Path.rglob
.
Что можно сделать, чтобы обойти эту проблему, и почему это проблема в первую очередь?
Комментарии:
1. В документации Microsoft говорится, что максимальная длина пути для большинства функций в Windows API составляет 260 символов.
Ответ №1:
Проблема в том, что большинство функций файловой системы Windows не принимают пути, которые выглядят как:
r'C:longfilepathof256characters'
Таким образом, pathlib и Excel обнаруживают, что они не могут открыть файл или прочитать каталог, используя эти функции Windows.
Хорошей новостью является то, что функции Windows принимают пути, которые выглядят как:
r'\?C:longfilepathof256characters'
Плохая новость заключается в том, что pathlib не всегда правильно соединяет пути такого типа:
>>> Path(r'\?foo').joinpath(r'\?bar')
WindowsPath('//?/foo/bar') # correct
>>> Path(r'\?foo', r'\?bar')
WindowsPath('//?/bar') # incorrect
>>> Path(r'\?c:foo').joinpath(r'c:bar')
WindowsPath('c:/bar') # correct, but not the result we want
Другая плохая новость заключается в том, что такие пути несколько ограничены: когда путь, ведущий к функции файловой системы Windows, начинается с \?
, вы не можете использовать косые черты или одинарные или двойные точки.
Хорошей новостью является то, что функция, подобная следующей, преобразует практически любой беспорядочный путь, который вы придумали, во что-то, что работает:
def longname(path):
return pathlib.Path('\\?\' os.fspath(path.resolve()))
Помните, что resolve()
удаляет \?
только с начала, path
если path
действительно существует, поэтому приведенный выше код не работает в случае, когда path
не существует и уже есть \?
. Итак, либо убедитесь, что ваша программа использует «обычные» пути без префикса и вызывает longname()
в последнюю очередь перед выполнением каких-либо реальных файловых операций, либо улучшите longname()
:
def longname(path):
normalized = os.fspath(path.resolve())
if not normalized.startswith('\\?\'):
normalized = '\\?\' normalized
return pathlib.Path(normalized)
Поведение Windows задокументировано Microsoft: https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file#maximum-path-length-limitation
Комментарии:
1. Из ссылки, которой вы поделились, кажется, что точки и двойные точки принимаются как часть имен файлов (например,
file..txt
), просто не интерпретируются как относительные пути, как в..file.txt
.2. Можем ли мы настроить это так, чтобы оно работало в Windows и Linux? 🙂