使用github webhooks,我希望能够将任何更改提取到远程开发服务器。目前,当在适当的目录中时,git pull
会获得需要进行的任何更改。但是,我无法弄清楚如何从Python中调用该函数。我尝试过以下方法:
import subprocess
process = subprocess.Popen("git pull", stdout=subprocess.PIPE)
output = process.communicate()[0]
但是这会导致以下错误
Traceback(最近一次调用最后一次):文件“”,第1行,in 文件“/usr/lib/python2.7/subprocess.py”,第679行,in 的初始化 errread,errwrite)文件“/usr/lib/python2.7/subprocess.py”,第1249行,在_execute_child中 raise child_exception OSError:[Errno 2]没有这样的文件或目录
有没有办法可以在Python中调用这个bash命令?
答案 0 :(得分:111)
你考虑过使用GitPython吗?它旨在为您处理所有这些废话。
import git
g = git.cmd.Git(git_dir)
g.pull()
答案 1 :(得分:35)
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。
答案 2 :(得分: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
,依此类推。
答案 3 :(得分:2)
使用GitPython接受的答案比直接使用subprocess
更好。
这种方法的问题在于,如果您想解析输出,最终将看到“瓷器”命令which is a bad idea
的结果。以这种方式使用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")
答案 4 :(得分:2)
如果您使用的是Python 3.5+,则可以使用subprocess.run
而不是subprocess.Popen
。例如:
import subprocess
subprocess.run(["git", "pull"], check=True, stdout=subprocess.PIPE).stdout
答案 5 :(得分:-3)
尝试:
subprocess.Popen("git pull", stdout=subprocess.PIPE, shell=True)