Eryk Sun <[email protected]> added the comment:
> To get the correct output, cmd has a "/u" switch (this switch has
> probably existed forever - at least since Windows NT 4.0, by my
> internet search). The output can then be decoded using
> encoding='utf-16-le', like any native Windows string.
However, the /u switch doesn't affect how CMD reads from stdin when it's a disk
file or pipe. For example, `set /p` will stop at the first NUL byte. In general
this is mismatched with subprocess, which provides a single `encoding` value
for all 3 standard I/O streams. For example:
>>> r = subprocess.run('cmd /d /v /u /c "set /p spam= & echo !spam!"',
... capture_output=True, input='spam', encoding='oem')
>>> r.stdout
's\x00p\x00a\x00m\x00\n\x00\n\x00'
With UTF-16 input, CMD only reads up to "s" instead of reading the entire
"s\x00p\x00a\x00m\x00" string that was written to stdin:
>>> r = subprocess.run('cmd /d /v /u /c "set /p spam= & echo !spam!"',
... capture_output=True, input='spam', encoding='utf-16le')
>>> r.stdout
's\n'
> 1. A new argument to Popen
This may lead to confusion and false bug reports by people who expect the
setting to also affect external programs run via the shell (e.g. tasklist.exe).
It's also not consistent with how CMD reads from stdin, as shown above.
I can see the use of adding a cross-platform get_shell_path() function that
returns the fully-qualified path to the shell that's used by shell=True. This
way programs don't have to figure it out on their own if they need custom shell
options.
Common CMD shell options in Windows include /d (skip AutoRun commands), /v
(enable delayed expansion of environment variables via "!"), /e (enable command
extensions), /k (remain running after the command), and /u. I'd prefer
subprocess to use /d by default. It's strange that the CRT's system() command
doesn't use it.
Currently the shell path can be "/bin/sh" or "/system/bin/sh" in POSIX and
os.environ.get("COMSPEC", "cmd.exe") in Windows. I'd prefer that Windows
instead used:
shell_path = os.path.abspath(os.environ.get('ComSpec',
os.path.join(_winapi.GetSystemDirectory(), 'cmd.exe')))
i.e. never use an unqualified, relative path such as "cmd.exe".
Instead of the single-use GetSystemDirectory function, it could instead use
_winapi.SHGetKnownFolderPath(_winapi.FOLDERID_System), or
_winapi.SHGetKnownFolderPath('{1AC14E77-02E7-4E5D-B744-2EB1AE5198B7}') if the
GUID constants aren't added.
----------
nosy: +eryksun
_______________________________________
Python tracker <[email protected]>
<https://bugs.python.org/issue33780>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com