【问题标题】:pathlib Path.rglob fails on long file paths in Windowspathlib Path.rglob 在 Windows 中的长文件路径上失败
【发布时间】:2019-09-12 21:34:15
【问题描述】:

我正在尝试返回特定位置中所有文件和子文件夹的列表。我的代码如下:

from pathlib import Path
FOLDER_PATH = Path(r'C:\long\file\path\of\138\characters\')

我收到错误: FileNotFoundError: [WinError 3] The system cannot find the path specified:

错误发生在文件夹路径上,而不是文件上,所以我不确定这是否是原因。

当我手动进入文件夹并尝试打开其中的PDF 时,我收到“打开此文档时出错。找不到此文件。”

同样,当我尝试打开 XLSX 文件时,我得到“无法访问此文件。请尝试以下操作之一:(确保它存在,不是只读的,不超过 218字符等)”

此文件夹中的文件路径肯定超过 218 个字符,我理解这可能是 Excel 的问题,但我不明白为什么 pathlib.Path.rglob 列出它们会有问题,有人明白吗? ?

但是,如果我使用 CMD (dir /s /b > files.txt),我可以获取列表。

此外,如果我随后在 python 中将files.txt 导入Path 对象列表paths 并尝试执行[x.is_file() for x in paths],它将无法正确地将一些较长的路径识别为文件。

我已验证,如果我在本地复制目录(存在更短的路径),Excel 和pathlib.Path.rglob 可以访问这些文件。

可以做些什么来解决这个问题,为什么它首先会成为一个问题?

【问题讨论】:

标签: python python-3.x path pathlib


【解决方案1】:

问题在于大多数 Windows 文件系统函数不接受如下所示的路径:

r'C:\long\file\path\of\256\characters'

因此 pathlib 和 Excel 都发现它们无法使用这些 Windows 函数打开文件或读取目录。

好消息是 Windows 函数确实接受如下所示的路径:

r'\\?\C:\long\file\path\of\256\characters'

坏消息是 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 不存在且已经有@ 的情况下不起作用987654332@。因此,要么确保你的程序使用没有前缀的“普通”路径,并在执行任何实际文件操作之前将longname() 作为最后一件事,要么增强longname()

def longname(path):
    normalized = os.fspath(path.resolve())
    if not normalized.startswith('\\\\?\\'):
        normalized = '\\\\?\\' + normalized
    return pathlib.Path(normalized)

Microsoft 记录了 Windows 行为:https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file#maximum-path-length-limitation

【讨论】:

  • 从您共享的链接中,点和双点似乎被接受为文件名的一部分(例如\file..txt),只是不像\..\file.txt 那样被解释为相对路径。跨度>
猜你喜欢
  • 2021-09-06
  • 1970-01-01
  • 2015-06-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多