2013-03-09 71 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