error in os.chdir

eryk sun eryksun at gmail.com
Sun Jul 1 11:22:23 EDT 2018


On Sun, Jul 1, 2018 at 8:50 AM, Steven D'Aprano
<steve+comp.lang.python at pearwood.info> wrote:
> On Sun, 01 Jul 2018 03:18:23 +0000, eryk sun wrote:
>
>> The Windows API handles this, but not for a path that begins with \\?\.
>
> But what about the *Python* API? The Python open() function, and all the
> high-level os.* and os.path.* functions which take paths as strings are
> supposed to automatically convert forward slashes to backslashes. Aren't
> they?

Python's I/O functions don't modify file paths, except to decode bytes
paths in 3.6+.

os.path.normpath uses backslash in Windows, without involving the OS,
as does pathlib in Python 3. os.path.abspath calls WinAPI
GetFullPathName to get a canonical, fully-qualified path, including
transforming reserved paths, e.g.

    >>> os.path.abspath('C:/Temp/conout$.txt')
    '\\\\.\\conout$'

    >>> os.path.abspath('C:/Temp/spam. . .')
    'C:\\Temp\\spam'

(Note that the above "conout$" example is for Windows 8 and 10. In
prior versions, "conin$" and "conout$"  aren't reserved in
qualified-relative or absolute paths, only when passed to CreateFile
as unqualified names.)

The \\?\ prefix allows using otherwise reserved names such as "con"
and "spam...".

For versions of Windows prior to 10 or Python prior to 3.6, the \\?\
prefix is also the only way to get past the 260 character limit of
legacy DOS paths to work with paths with up to 32K characters. Python
3.6+ is manifested to support long paths in Windows 10 without
requiring the \\?\ prefix. This can be enabled by setting the
LongPathsEnabled value in
"HKLM\System\CurrentControlSet\Control\FileSystem". Maybe in a future
version this registry setting will be enabled by default.

>> Bear in mind that forward slash is just a  name character in NT.
>
> Interesting...
>
> That's rather like on HFS Plus, where / is an ordinary character allowed
> in file names (although Mac OS goes to extraordinary effort to ensure
> that tools that expect / as a path separator see it, and those which
> expect : as the path separator see it instead).

Many characters are reserved in Windows file systems that aren't
generally reserved in NT, including forward slash. What happens here
is that the Object Manager hands off parsing the rest of a path as
soon as it reaches an object that has a parse procedure. This allows
object types such as Key and Device objects to implement custom
namespaces.

The Configuration Manager's (registry) Key parse procedure limits
names to 256 characters and the tree depth to 512 keys. (Note that
HKCU is a pseudo-handle for "\Registry\User\<sid>", so subtract 3 from
the depth.) However it doesn't reserve characters, except for the
native backslash path separator. IIRC it allows NUL in key names, but
that would render them impossible to access in the Windows API, which
uses null-terminated strings.

The I/O Manager's Device parse procedure sends an IRP_MJ_CREATE I/O
request packet either to the first device in the stack (including
lower/upper filter drivers), or to the file-system device stack that's
managing it. The I/O manager doesn't reserve additional characters or
limit name length, but most file systems limit names to 255 characters
(127 for UDF) and reserve backslash (path separator), slash, colon,
pipe, wildcards (*?<>"), and ASCII controls. In contrast, the named
pipe file system (i.e. WinAPI \\.\PIPE or native \Device\NamedPipe) is
extremely lenient. Pipe names can be up to 259 characters and can
include any character except NUL. This file system doesn't support
directories, so pipe names can even include backslash, which is a
common practice.

Except for disk volumes, most devices aren't file systems or managed
by one. However, sometimes they do implement a simple namespace of
hard-coded names. For example, the console device "\Device\ConDrv"
implements a few names such as "Connect", "Input", "Output", "Console"
(con), "CurrentIn" (conin$), and "CurrentOut" (conout$).


More information about the Python-list mailing list