Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make subprocess find git executable on Windows

import subprocess

proc = subprocess.Popen('git status')
print 'result: ', proc.communicate()

I have git in my system path, but when I run subprocess like this I get:
WindowsError: [Error 2] The system cannot find the file specified

How can I get subprocess to find git in the system path?

Python 2.6 on Windows XP.

like image 349
Jesse Aldridge Avatar asked Feb 11 '11 02:02

Jesse Aldridge


1 Answers

The problem you see here is that the Windows API function CreateProcess, used by subprocess under the hood, doesn't auto-resolve other executable extensions than .exe. On Windows, the 'git' command is really installed as git.cmd. Therefore, you should modify your example to explicitly invoke git.cmd:

import subprocess

proc = subprocess.Popen('git.cmd status')
print 'result: ', proc.communicate()

The reason git works when shell==True is that the Windows shell auto-resolves git to git.cmd.

Eventually, resolve git.cmd yourself:

import subprocess
import os.path

def resolve_path(executable):
    if os.path.sep in executable:
        raise ValueError("Invalid filename: %s" % executable)

    path = os.environ.get("PATH", "").split(os.pathsep)
    # PATHEXT tells us which extensions an executable may have
    path_exts = os.environ.get("PATHEXT", ".exe;.bat;.cmd").split(";")
    has_ext = os.path.splitext(executable)[1] in path_exts
    if not has_ext:
        exts = path_exts
    else:
        # Don't try to append any extensions
        exts = [""]

    for d in path:
        try:
            for ext in exts:
                exepath = os.path.join(d, executable + ext)
                if os.access(exepath, os.X_OK):
                    return exepath
        except OSError:
            pass

    return None

git = resolve_path("git")
proc = subprocess.Popen('{0} status'.format(git))
print 'result: ', proc.communicate()
like image 180
aknuds1 Avatar answered Oct 10 '22 16:10

aknuds1