Windows上的python长路径 - os.stat()失败了相对路径?

时间:2018-03-01 16:26:57

标签: python windows path

我想在Windows上访问一些长UNC路径。我知道我需要使用"\\?\UNC\"前缀(如果你转义斜杠,则为"\\\\?\\UNC\\")。这很好用:

os.stat('\\\\?\\UNC\\server.example.com\\that\\has\\long\\path\\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\\bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.txt')
# works, returns os.stat_result

然而,它似乎以相对路径失败:

os.chdir('\\\\?\\UNC\\server.example.com\\that\\has\\long\\path')
os.getcwd()
# returns '\\\\?\\UNC\\server.example.com\\that\\has\\long\\path'
os.stat('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\\bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.txt')
# fails with [WinError 3] The system cannot find the path specified: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\\bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.txt'

这可能是Python中的错误,还是我的代码错了?

旁注 - 解决方法是os.stat(os.path.abspath('aaa\\bbb.txt'))

1 个答案:

答案 0 :(得分:4)

在Windows 10中,您可以通过设置名为" LongPathsEnabled"的DWORD来为系统启用长路径支持。在" HKLM \ System \ CurrentControlSet \ Control \ FileSystem"。这允许声明支持其清单中的长路径的应用程序使用内核支持的最大路径长度(大约32,760个字符,具体取决于最终解析的路径),甚至不需要" \\ ?\"字首。 Python 3.6+表现为支持长路径。

也就是说,在Windows 10之前,工作目录和相对路径不能超过MAX_PATH(260)个字符,其中包括尾部反斜杠和NUL终止符。目前的文件在这一点上具有误导性。显然有人添加了免责声明"将此限制扩展到32,767个宽字符......"到SetCurrentDirectory的文档。不,没有延长限制。这就是它所说的circa 2016

进程的当前工作目录是DOS路径,而不是本机内核路径(*)。 DOS路径是任何非Unicode的路径,或使用正斜杠,DOS设备(例如逻辑驱动器号,CON,NUL等)或UNC语法。必须通过ntdll.dll中的运行时库函数将DOS路径转换为本机路径。如果长路径支持不可用,则此隐式转换仅限于最多MAX_PATH个字符。

解决这个问题需要使用以" \\?\"开头的完全限定的Unicode路径。字首。此前缀告诉运行时库绕过路径转换。相反,它只是替换了" \\?\"内核的前缀" \ ?? \" DOS设备链接的虚拟目录,路径最终解析为真正的NT设备(例如" \\?\ UNC" =>" \ ?? \ UNC" =>& #34; \设备\ MUP"。)

(*)内核命名空间对所有内核对象使用单根树,而不仅仅是设备对象。它还有一种更可靠的处理相对路径的方法;请参阅OBJECT_ATTRIBUTESRootDirectory字段。