12
votes

Faire sous-traduction Trouver Git exécutable sur 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 specifiedHow can I get subprocess to find git in the system path?Python 2.6 on Windows XP.

2 commentaires

Le vrai problème n'est pas que la sous-processus n'utilise pas path , mais que GIT est installé comme "git.cmd", plutôt que "git.exe", qui serait trouvé par subprocess.popen.


Cela a eu lieu pour moi à l'aide de sous-processus.check_output (...) sous Windows 10 après la mise à jour de GIT à 2.19.1. Travaillé avant la mise à jour. Maintenant ne fonctionne même pas avec shell = true .


4 Réponses :


0
votes

Vous voulez dire xxx

le premier argument de subprocess.popen prend un shlex.split -itant la liste des arguments.

ou: xxx

Ceci n'est pas recommandé, car vous lancez une coquille puis lancez un processus dans la coque.

aussi, Vous devriez utiliser stdout = sous-processus.pipe pour récupérer le résultat.


9 commentaires

Non, popen prend une chaîne ou une liste. Voir docs.python.org/library/subprocess.html


Dépend - si vous avez des arguments, vous devez utiliser une liste. Sinon, vous invoquez simplement "statut git" et non statut git .


Non, cela ne dépend pas, voir docs.python.org/library /subprocess.html#replacing-Os-system . Veuillez lire les docs avant de répandre une désinformation. Le module de sous-processus peut être assez déroutant tel qu'il est.


shell = true est requis si vous n'utilisez pas une liste d'arguments.


C'est parce que vous êtes sur un système UNIX, avec shell = false , argument par défaut. Sur Unix avec shell = true , il fonctionnerait "correctement". Il convertit des listes en une chaîne en interne de toute façon sur Windows. Encore une fois, veuillez lire la documentation.


Quelle erreur recevez-vous? Les docs sont assez explicites sur la seule fois où vous devez passer shell = true sous Windows étant si vous exécutez une coque intégrée. Si vous voyez un comportement incorrect, un rapport de bogue est probablement en ordre.


Votre premier extrait donne la même erreur, mais le second fonctionne.


Oh Lordy, vous avez en effet besoin shell = true si vous êtes sous Windows, peut-être. Voir BOGS.PLYTHON.ORG/ISSUE8557 . La discussion dans les commentaires est éclairante,


La raison pour laquelle l'invocation Shell fonctionne est simplement que la coquille auto-résolve «Git» contre «git.cmd», pas seulement «git.exe» comme l'API Windows.



-2
votes

Je pense que vous devez passer env pour popen, quelque chose comme: xxx

devrait faire le tour.


1 commentaires

Le env est équivalent à Os.environ.



12
votes

Le problème que vous voyez ici est que la fonction Windows API CreateProcess , utilisé par sous-processus sous la hotte, ne résolvait pas automatiquement d'autres extensions exécutables que .exe code>. Sous Windows, la commande 'git' est vraiment installée comme git.cmd code>. Par conséquent, vous devez modifier votre exemple pour appeler explicitement git.cmd code>: xxx pré>

la raison git code> fonctionne lorsque shell == Vrai code> est que le shell de Windows résolve auto-résolve git code> à git.cmd code>. P>

finalement, résoudre votre git.cmd vous-même: H2>
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()


4 commentaires

Ah d'accord. Je n'utilise plus Windows, donc je ne peux donc pas confirmer cette réponse, mais je vais juste supposer que vous avez raison. Merci.


Vérifiez également [ce rapport de bogue Python] [1]. [1]: BOGS.PLYTHON.ORG/issue17023 "Si vous ajoutez un répertoire au chemin sous Windows afin que le répertoire est dans des guillemets, la sous-traité ne trouve pas d'exécutables dedans. "


La variable d'environnement qui répertorie les extensions exécutables est appelée pathext, pas des pathextes. (Le code comme indiqué sera toujours revenant à ".exe; .bat; .cmd", car les pathextes n'existeront généralement pas.)


@Dairahopwood merci, corrigé.



0
votes

Notez qu'en 2020, avec Git 2,28 (Q3 2020), Python 2.6 ou plus n'est plus pris en charge.

Voir commettras 45a87a8 (7 juin 2020) par Denton Liu ( Denton-L )
(issu de la fusion par Junio ​​Hamano C - gitster - commit 6361eb7 18 Jun 2020)

CodingGuidelines : spécifier Python 2.7 est la plus ancienne Version

Signed-off-by: Denton Liu

0b4396f068 ( " git-p4 : faire python2.7 la version prise en charge la plus ancienne "13/12/2019, Git v2.27.0-RC0 - lot # 1 ), était git-p4 mis à jour pour seulement 2.7 et plus récent. Depuis Python 2.6 est à peu près l'histoire ancienne, CodingGuidelines de mise à jour pour montrer que 2.7 est la plus ancienne version prise en charge.


0 commentaires