使子进程在 Windows 上找到 git 可执行文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4965175/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 16:09:15  来源:igfitidea点击:

Make subprocess find git executable on Windows

pythonwindowsgitpathsubprocess

提问by Jesse Aldridge

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

我的系统路径中有 git,但是当我像这样运行子进程时,我得到:
WindowsError: [Error 2] The system cannot find the file specified

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

如何让子进程在系统路径中找到 git?

Python 2.6 on Windows XP.

Windows XP 上的 Python 2.6。

采纳答案by aknuds1

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:

您在此处看到的问题是 Windows API 函数CreateProcess由子进程在幕后使用,不会自动解析除.exe. 在 Windows 上,'git' 命令实际上安装为git.cmd. 因此,您应该修改您的示例以显式调用git.cmd

import subprocess

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

The reason gitworks when shell==Trueis that the Windows shell auto-resolves gitto git.cmd.

究其原因git,当工作shell==True是,Windows外壳程序自动做出决议gitgit.cmd

Eventually, resolve git.cmd yourself:

最后,自己解决 git.cmd :

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()

回答by aknuds1

You mean

你的意思是

proc = subprocess.Popen(["git", "status"], stdout=subprocess.PIPE)

The first argument of subprocess.Popentakes a shlex.split-like list of arguments.

的第一个参数subprocess.Popen采用类似参数shlex.split列表。

or:

或者:

proc = subprocess.Popen("git status", stdout=subprocess.PIPE, shell=True)

This is not recommended, as you are launching a shell then launching a process in the shell.

不建议这样做,因为您要启动 shell,然后在 shell 中启动进程。

Also, you should use stdout=subprocess.PIPEto retrieve the result.

此外,您应该使用stdout=subprocess.PIPE检索结果。

回答by jdd

I believe you need to pass envin to Popen, something like:

我相信您需要传入envPopen,例如:

import subprocess, os
proc = subprocess.Popen('git status', env=os.environ, stdout=subprocess.PIPE)

Should do the trick.

应该做的伎俩。