90

使用 github webhooks,我希望能够将任何更改拉到远程开发服务器。目前,当在适当的目录中时,git pull获取需要进行的任何更改。但是,我不知道如何从 Python 中调用该函数。我尝试了以下方法:

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

但这会导致以下错误

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/subprocess.py", line 679, in __init__
    errread, errwrite)
  File "/usr/lib/python2.7/subprocess.py", line 1249, in _execute_child
    raise child_exception
OSError: [Errno 2] No such file or directory

有没有办法可以从 Python 中调用这个 bash 命令?

4

6 回答 6

160

你考虑过使用 GitPython 吗?它旨在为您处理所有这些废话。

import git 

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

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

于 2013-03-09T20:38:43.420 回答
58

subprocess.Popen需要程序名称和参数的列表。您正在向它传递一个字符串,它(使用默认值shell=False)等效于:

['git pull']

这意味着 subprocess 试图找到一个名为 literal 的程序git pull,但没有这样做:在 Python 3.3 中,您的代码引发了 exception 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-pythonDulwich

于 2013-03-09T20:34:19.977 回答
27

使用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")
于 2018-11-02T01:22:15.993 回答
2

这是一个示例配方,我一直在我的一个项目中使用。同意有多种方法可以做到这一点。:)

>>> 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,依此类推。

于 2013-03-09T20:42:05.707 回答
1

如果您使用 Python 3.5+,则更喜欢它subprocess.run可以subprocess.Popen处理的场景。例如:

import subprocess
subprocess.run(["git", "pull"], check=True, stdout=subprocess.PIPE).stdout
于 2020-05-21T23:56:59.633 回答
-2

尝试:

subprocess.Popen("git pull", stdout=subprocess.PIPE, shell=True)
于 2013-03-09T20:41:28.613 回答