web-dev-qa-db-ja.com

Python内から「git pull」を呼び出すにはどうすればよいですか?

Github webhookを使用して、リモート開発サーバーに変更をプルできるようにしたいと思います。現時点では、適切なディレクトリにある場合、git pullは、必要な変更を取得します。ただし、Python内からその関数を呼び出す方法はわかりません。私は次を試しました:

import subprocess
process = subprocess.Popen("git pull", stdout=subprocess.PIPE)
output = process.communicate()[0]

しかし、これは次のエラーになります

トレースバック(最後の最後の呼び出し):ファイル ""、行1、ファイル "/usr/lib/python2.7/subprocess.py"、行679、init errread、errwrite)ファイル " /usr/lib/python2.7/subprocess.py "、行1249、_execute_child raise child_exception OSError:[Errno 2] No such file or directory

Python内からこのbashコマンドを呼び出す方法はありますか?

59
djq

GitPythonの使用を検討しましたか?それはあなたのためにこのすべてのナンセンスを処理するように設計されています。

import git 

g = git.cmd.Git(git_dir)
g.pull()

https://github.com/gitpython-developers/GitPython

115
jleahy

subprocess.Popen プログラム名と引数のリストが必要です。それに単一の文字列を渡します。これは(デフォルトのShell=Falseで)次と同等です:

['git pull']

つまり、サブプロセスは文字通りgit pullという名前のプログラムを見つけようとしますが、失敗します:Python 3.3では、コードは例外FileNotFoundError: [Errno 2] No such file or directory: 'git pull'を発生させます。代わりに、次のようなリストを渡します。

import subprocess
process = subprocess.Popen(["git", "pull"], stdout=subprocess.PIPE)
output = process.communicate()[0]

ところで、Python 2.7+では、このコードを check_output 便利な関数で簡素化できます:

import subprocess
output = subprocess.check_output(["git", "pull"])

また、git機能を使用するために、gitバイナリを呼び出す必要はありません(単純で移植性はありますが)。 git-python または Dulwich の使用を検討してください。

36
phihag

GitPython を使用して受け入れられる答えは、単にsubprocessを直接使用するよりも少し良いです。

このアプローチの問題は、出力を解析したい場合、最終的に「磁器」コマンドの結果を見ることになります これは悪い考えです

この方法でGitPythonを使用することは、光沢のある新しいツールボックスを取得し、それを使用して、内部のツールの代わりにそれを固定するネジの山に使用するようなものです。 APIが使用されるように設計された方法は次のとおりです。

import git
repo = git.Repo('Path/to/repo')
repo.remotes.Origin.pull()

何かが変更されたかどうかを確認したい場合は、使用できます

current = repo.head.commit
repo.remotes.Origin.pull()
if current != repo.head.commit:
    print("It changed")
3
Eric

これはサンプルレシピで、私のプロジェクトの1つで使用しています。ただし、これを行うには複数の方法があることに同意しました。 :)

_>>> import subprocess, shlex
>>> git_cmd = 'git status'
>>> kwargs = {}
>>> kwargs['stdout'] = subprocess.PIPE
>>> kwargs['stderr'] = subprocess.PIPE
>>> proc = subprocess.Popen(shlex.split(git_cmd), **kwargs)
>>> (stdout_str, stderr_str) = proc.communicate()
>>> return_code = proc.wait()

>>> print return_code
0

>>> print stdout_str
# On branch dev
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#   file1
#   file2
nothing added to commit but untracked files present (use "git add" to track)

>>> print stderr_str
_

コードの問題は、subprocess.Popen()の配列を渡していないため、_git pull_という単一のバイナリを実行しようとしていたことです。代わりに、最初の引数がgitなどであるバイナリpullを実行する必要があります。

2
Tuxdude