Author eryksun
Recipients asvetlov, chris.jerdonek, cvrebert, damon-atkins, docs@python, eryksun, gregory.p.smith, ned.deily, paul.moore, pepalogik, python-dev, steve.dower, tim.golden, wolma, zach.ware
Date 2021-03-17.01:02:37
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1615942959.94.0.203620417742.issue15533@roundup.psfhosted.org>
In-reply-to
Content
> Python is conceptually multi-platform, so its behavior on 
> Linux and Windows should be as much consistent as possible.

It's not expected for the behavior of all Popen() parameters to be the same on all platforms. For example, the behavior and capabilities of shell=True are different in Windows vs POSIX. But I think a basic set of parameters should have been singled out for cross-platform consistency -- at least in the default case. Unfortunately it wasn't designed that way. New behavior that's consistent with POSIX can be implemented, but at this point it would have to be enabled by a parameter. 

> "In particular, the function looks for executable (or for the 
> first item in args) relative to cwd if the executable path is 
> a relative path." 

For POSIX, this should be stated as a "relative path without a slash in it" or a "relative path without a directory in it". An unqualified filename is a relative path that won't be resolved against `cwd`, unless there's a "." entry in PATH.

For Windows, the use of CreateProcess() is documented. It could be stated more explicitly that `executable`, `args` / list2cmdline(args), `env`, and `cwd` are passed directly to CreateProcess() as lpApplicationName, lpCommandLine, lpEnvironment, and lpCurrentDirectory.

Here are some notes and corrections about the documentation of lpCommandLine, in particular the following paragraph:

    If the file name does not contain an extension, .exe is appended.
    Therefore, if the file name extension is .com, this parameter must
    include the .com extension. If the file name ends in a period (.)
    with no extension, or if the file name contains a path, .exe is
    not appended. If the file name does not contain a directory path,
    the system searches for the executable file in the following
    sequence [1][2][3]:

        * %__APPDIR__%
        * %__CD__% [4]
        * %SystemRoot%\System32
        * %SystemRoot%\System
        * %SystemRoot%
        * %PATH% (machine/user extended search sequence)

    [1] The search sequence is rewritten here succinctly using
        environment variables in the current process, including the
        virtual variables __APPDIR__ (application directory) and
        __CD__ (current directory), which are supported by WinAPI
        GetEnvironmentVariableW().

    [2] A path name is resolved by searching for it if it isn't fully
        qualified and doesn't explicitly begin with the current
        directory (".") or its parent (".."). Note that, unlike POSIX,
        a relative path name is resolved by searching for it even if
        it contains a directory component (i.e. a slash or backslash).
        For example, "spam\eggs.exe" is resolved by looking for
        r"%__APPDIR__%\spam\eggs.exe" and so on.

    [3] If a path name has to be resolved by searching, and its final
        component does not contain a "." character, then ".exe" is
        appended to the name. On the other hand, if a path name does
        not need to be resolved by searching, because it's fully
        qualified or the first component is "." or "..", then if the 
        given path name doesn't exist, it also looks for the name with
        ".exe" appended, even if the final component of the path name
        contains a "." character.

    [4] If "NoDefaultCurrentDirectoryInExePath" is defined in the
        environment and the path name does not contain a directory
        component (i.e. no slash or backslash), then the current
        directory is excluded from the search sequence.

That %__APPDIR__% always takes precedence means that subprocess.Popen(['python']) runs the Python version of the current process, regardless of PATH, unless shell=True is used. 

The implementation of lpApplicationName (executable) and lpCurrentDirectory (cwd) means that argv[0] in the child process, as parsed from its command line, does not necessarily resolve to a name in the filesystem. Windows supports GetModuleFileNameW(NULL, ...) to get the path of the application executable.
History
Date User Action Args
2021-03-17 01:02:40eryksunsetrecipients: + eryksun, gregory.p.smith, paul.moore, tim.golden, ned.deily, cvrebert, asvetlov, chris.jerdonek, docs@python, python-dev, zach.ware, steve.dower, pepalogik, wolma, damon-atkins
2021-03-17 01:02:39eryksunsetmessageid: <1615942959.94.0.203620417742.issue15533@roundup.psfhosted.org>
2021-03-17 01:02:39eryksunlinkissue15533 messages
2021-03-17 01:02:37eryksuncreate