2013-03-09 234 views
38

使用github webhooks,我希望能够对远程开发服务器进行任何更改。目前,在适当的目录中,git pull会得到所需的任何更改。但是,我无法弄清楚如何在Python中调用该函数。我曾尝试以下:如何从Python内部调用'git pull'?

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

但是,这会导致以下错误

Traceback (most recent call last): File "", line 1, in 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命令的方法吗?

+0

这是一个重复http://stackoverflow.com/questions/4256107/running-bash-commands-in-python – ceptno 2013-03-09 20:32:16

+2

@Brandon这不是真的,还有很多其他的解决方案,最好的。 – jleahy 2013-03-09 20:34:01

+0

PATH中的'git'可执行文件? – poke 2013-03-09 20:41:54

回答

28

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-pythonDulwich

+0

每个文档:*“参数应该是程序参数序列**或者单个字符串**。”*(强调我的)。你确定这一点,因为它适合我吗? – poke 2013-03-09 20:39:43

+0

@poke是的,文档有点不清楚。如果你想传入一个字符串,你必须传递'shell = True'。 – phihag 2013-03-09 20:44:26

+0

那么,正如我所说的,它只适用于'subprocess.Popen(“git pull”,stdout = subprocess.PIPE).communicate()'(Windows上的3.3和2.7)。 - 好了,再读一点,文档解释说,只有在没有传递任何参数的情况下,这只会在Unix上起作用。Nevermind then ^^ – poke 2013-03-09 20:45:30

-4

尝试:

subprocess.Popen("git pull", stdout=subprocess.PIPE, shell=True) 
+2

虽然这会不必要地产生shell,不是吗? – phihag 2013-03-09 20:52:14

+0

请参阅上面的答案(http://stackoverflow.com/a/15315617/679449) – Kermit 2014-03-19 18:58:08

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

+1

不是说'split'应该是真的['shlex.split'](http://docs.python.org/2 /library/shlex.html#shlex.split),并且该代码是不必要的复杂的 - 在'沟通'之后,您不需要'等待',对于大多数使用情况,['check_output'](http:// docs。 python.org/3/library/subprocess.html#subprocess.check_output)已经做了正确的字符串。 – phihag 2013-03-09 20:55:16

+0

我使用wait()来收集进程的返回码,以满足我的需要。如果OP对返回码检查不感兴趣,则是可选的。虽然同意使用'shlex.split'。如果你对抓取stdout或stderr不感兴趣,可以跳过这些。提供替代解决方案没有什么问题,它可以让你做更多的事情而不是标准的Python文档示例;) – Tuxdude 2013-03-09 20:57:16

+0

正如你所提到的,'check_output'仅在2.7以后才添加,我需要在python环境下运行我的脚本比这更老的版本。 – Tuxdude 2013-03-09 21:04:56