PEP idea: On Windows, subprocess should implicitly support .bat and .cmd scripts by using FindExecutable from win32 API

Stefan Zimmermann zimmermann.code at gmail.com
Thu May 7 11:45:19 EDT 2015


This discussion is getting really interesting and far beyond the actual topic :)
I want to add some additional thoughts on Popen:

Marko Rauhamaa wrote:
> Stefan Zimmermann:
> 
> > And last but not least, Popen behavior on Windows makes it difficult
> > to write OS-independent Python code which calls external commands that
> > are not binary by default:
> 
> Then, write OS-dependent Python code.

Then you even have to write tool-distribution-dependent code.
Especially Unix tools are often distributed in many different variants for Windows. Some installers expose .exe, some .bat, some .cmd files to the user. So you always have to explicitly support any variant. Or run everything through 'cmd /c ...', which is as mentioned a real overhead for .exe files. Or you always have to manually use the win32 API, just to call a simple external tool. 

Calling an external command should be one of the simplest tasks in a high level scripting language like Python. And that should not involve any OS-specific differences, unless you want to use some advanced process handling features which are only supported by some specific OS.

Meanwhile I checked Ruby and Perl regarding this feature. Both support it. In both langs every standard function that calls external commands (like Perl's exec() or system() or Ruby's exec() or system() or IO.popen()), whether they invoke a shell or call it directly, support running 'tool.bat' or 'tool.cmd' by just writing 'tool'. Python almost seems to be the only major scripting language which does not support this implicitly.

Dave Angel wrote:
> It's a nice goal.  But these aren't OS features in Windows, they're 
> shell features.  And there are several shells.  If the user has 
> installed a different shell, is it Python's job to ignore it and 
> simulate what cmd.exe does?

In fact, it's something between OS and shell. Yes, .bat and .cmd files are always run thgrough cmd.exe. But on the OS level they are also condsidered executable files. And that doesn't depend on %PATHEXT% or any registered applications for file extensions on the explorer or shell level. On the OS level .exe, .com, .bat and .cmd is the exclusive set of extensions which are considered as executable. Not more and not less. When you search for the path of an executable with the win32 API, you can call FindExecutable with only 'tool' and you will get '...\tool.exe', '.com', '.bat' or '.cmd'. Whatever is found first according to PATH and precedence. Not more and not less. You can try that via pywin32 using win32api.FindExecutable().

And interestingly, Popen can call .bat and .cmd scripts directly if you explicitly specify the extension, also with shell=False. But it can't call any other file types even if that works in the shell because some application is registered for them on the explorer level, unless shell=True.

On Windows .bat and .cmd scripts have a special status beginning on the lowest OS level and a Windows user normally expects that any scripting language should be able to run them without explicit extension. Other major languages do it. Why not Python, too?



More information about the Python-list mailing list