I’ve been playing around in this general area recently w/regards to adding the ability to run external GUI diff tools in OverrideAudit
and investigated this particular phenomenon a bit.
More specifically I was curious what this was actually doing and looked at the source code in Python 3.3 itself to see what was happening. Note however that Sublime doesn’t necessarily use that version of the code as I believe the devs have their own version of it.
In any case, in Lib\subprocess.py
the Popen.__init__()
method invokes self._execute_child()
in order to start the child process, and the windows version of that method contains this:
if shell:
startupinfo.dwFlags |= _winapi.STARTF_USESHOWWINDOW
startupinfo.wShowWindow = _winapi.SW_HIDE
comspec = os.environ.get("COMSPEC", "cmd.exe")
args = '{} /c "{}"'.format (comspec, args)
That is, regardless of what Sublime may or may not be doing with the startupinfo
object itself, if you pass shell=true
to the Popen
contructor, it’s going to set that flag anyway and also specifically tell it to hide the window.
More importantly however, it starts your command by giving the command interpreter the /c
argument, which tells it to run the following command and then exit. So in essence the flag is actually just stopping the console window from briefly being displayed while the actual process starts.
Presumably this is also why the code in kill()
in the Sublime AsyncProcess
command has to do something more complex to terminate the running application under Windows; it can’t just stop what it tried to start because that process automatically terminated as soon as it launched the subtask.
If you look at the code for exec.py
, you’ll see that shell
is always set to True
when you use shell_cmd
, so this just automatically works if you do that. If you want to use cmd
instead, you need to specifically set shell
to True
in the command to ensure that the Python library does the right thing.
If I had to guess, I would say that Sublime is doing it this way on purpose for the same reason that the Python library seems to be doing it; so that it’s possible for you to launch an application hidden if you want it to be hidden, or not hidden if you don’t. On the other hand, possibly it’s just a happy accident that it works out that way. I would imagine that at least some subset of running a task in the background benefits from it not being visible, at any rate.