简体   繁体   中英

Curious behavior in sys.path when changing volumes in Windows CMD

I have just noticed some curious behavior of sys.path and Windows CMD and would like to know what is happening and why.

In the following two examples, I print out sys.path , change volume to D: , cd into a directory, change volume back to C: and finally print out sys.path again. I do this with two very similar PYTHONPATH s.

With PYTHONPATH=D:\\ :

C:\Users\z003w3we>python -c "import sys; print(sys.path)"
['', 'D:\\', <others>]

C:\Users\z003w3we>D:

D:\>cd UserData

D:\UserData>C:

C:\Users\z003w3we>python -c "import sys; print(sys.path)"
['', 'D:\\', <others>]

Everything is as expected.

With PYTHONPATH=D: (notice the missing trailing \\ ):

C:\Users\z003w3we>python -c "import sys; print(sys.path)"
['', 'D:\\', <others>]

C:\Users\z003w3we>D:

D:\>cd UserData

D:\UserData>C:

C:\Users\z003w3we>python -c "import sys; print(sys.path)"
['', 'D:\\UserData', <others>]

C:\Users\z003w3we>echo %PYTHONPATH%
D:

Now, instead of D: , we suddenly have D:\\UserData in sys.path . Notice that PYTHONPATH is unchanged.

I could not reproduce the same behavior with PowerShell; both PYTHONPATH s exhibit the first behavior.

As I said, I would be very interested in learning what is going on here.

CMD sets a conventionally hidden environment variable named "=D:" for the working directory on drive D:. The Python process inherits this environment variable, and the Windows API uses it when GetFullPathNameW is called to resolve the drive-relative path "D:" as a fully-qualified path.

In CMD we can list all environment variables including the 'hidden' ones via set "". This command depends on a bug, but one that's existed for so long that it's now a feature. To list just the hidden ones, use set "" | findstr /r "^=" set "" | findstr /r "^=" . For example:

C:\>set "" | findstr /r "^="
=C:=C:\

C:\>cd /d E:\UserData
E:\UserData>c:

C:\>set "" | findstr /r "^="
=C:=C:\
=E:=E:\UserData

C:\>set PYTHONPATH=E:
C:\>python -c "import sys; print(sys.path[1]); sys.exit(0xFF)"
E:\UserData

C:\>set "" | findstr /r "^="
=C:=C:\
=E:=E:\UserData
=ExitCode=000000FF

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM