Long paths for python on windows - os.stat() fails for relative paths?

三世轮回 提交于 2021-02-08 20:52:01

问题


I want to access some long UNC paths on Windows. I know that I need to use the "\\?\UNC\" prefix (which is "\\\\?\\UNC\\" if you escape the slashes). That works fine:

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

However, it seems to fail with a relative path:

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'

Might this be a bug in Python, or is my code wrong?

Sidenote - a workaround is os.stat(os.path.abspath('aaa\\bbb.txt')).


回答1:


In Windows 10, you can enable long-path support for the system by setting a DWORD named "LongPathsEnabled" in "HKLM\System\CurrentControlSet\Control\FileSystem". This allows applications that declare support for long paths in their manifest to use the maximum path length that's supported by the kernel (about 32,760 characters, depending on the final resolved path), without even requiring the "\\?\" prefix. Python 3.6+ is manifested to support long paths.

That said, prior to Windows 10, the working directory and relative paths cannot exceed MAX_PATH (260) characters, which includes the trailing backslash and NUL terminator. The current documentation is misleading on this point. Apparently someone added the disclaimer "to extend this limit to 32,767 wide characters..." to the docs for SetCurrentDirectory. No, there's no extending the limit. Here's what it said circa 2016.

The current working directory of a process is a DOS path, as opposed to a native kernel path (*). A DOS path is any path that's non-Unicode, or uses forward slashes, DOS devices (e.g. logical drive letters, CON, NUL, etc), or UNC syntax. DOS paths have to be translated to native paths by runtime-library functions in ntdll.dll. If long-path support isn't available, this implicit translation is limited to at most MAX_PATH characters.

Working around this requires using a fully-qualified Unicode path that begins with the "\\?\" prefix. This prefix tells the runtime-library to bypass path translation. Instead it simply replaces the "\\?\" prefix with the kernel's "\??\" virtual directory for DOS device links, and the path ultimately resolves to a real NT device (e.g. "\\?\UNC" => "\??\UNC" => "\Device\Mup").


(*) The kernel namespace uses a singly-rooted tree for all kernel objects, not just device objects. It also has a more reliable way of handling relative paths; see the RootDirectory field of OBJECT_ATTRIBUTES.



来源:https://stackoverflow.com/questions/49054305/long-paths-for-python-on-windows-os-stat-fails-for-relative-paths

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!