2010-12-22 32 views
64

我想使用子流程模塊在pythong中運行命令,並將輸出存儲在變量中。但是,我不希望將命令的輸出打印到終端。 對於此代碼:將子流程標準輸出轉換爲變量

def storels(): 
    a = subprocess.Popen("ls",shell=True) 
storels() 

我得到的終端目錄列表,而不是有它存儲在a。我也試過:

def storels(): 
     subprocess.Popen("ls > tmp",shell=True) 
     a = open("./tmp") 
     [Rest of Code] 
storels() 

這也打印ls的輸出到我的終端。我甚至用有點過時的os.system方法試過這個命令,因爲在終端中運行ls > tmp並不打印ls到終端,而是將它存儲在tmp中。然而,同樣的事情發生。

編輯:

我得到以下marcog的意見後,下面的錯誤,但運行更復雜的命令,只有當。 cdrecord --help。蟒蛇吐出了這一點:

Traceback (most recent call last): 
    File "./install.py", line 52, in <module> 
    burntrack2("hi") 
    File "./install.py", line 46, in burntrack2 
    a = subprocess.Popen("cdrecord --help",stdout = subprocess.PIPE) 
    File "/usr/lib/python2.6/subprocess.py", line 633, in __init__ 
    errread, errwrite) 
    File "/usr/lib/python2.6/subprocess.py", line 1139, in _execute_child 
    raise child_exception 
OSError: [Errno 2] No such file or directory 
+2

請注意,Python文檔中不鼓勵使用`shell = true`。 http://docs.python.org/2/library/subprocess.html#frequently-used-arguments – SamHuckaby 2013-12-09 16:13:51

回答

101

要獲得ls輸出,使用stdout=subprocess.PIPE

>>> proc = subprocess.Popen('ls', stdout=subprocess.PIPE) 
>>> output = proc.stdout.read() 
>>> print output 
bar 
baz 
foo 

命令cdrecord --help輸出到標準錯誤,所以你需要的是indstead管。你也應該把命令分解成一個令牌列表,就像我在下面所做的那樣,或者另一種方法是通過shell=True的參數,但是這會激發一個完整的shell,如果你不控制命令字符串。

>>> proc = subprocess.Popen(['cdrecord', '--help'], stderr=subprocess.PIPE) 
>>> output = proc.stderr.read() 
>>> print output 
Usage: wodim [options] track1...trackn 
Options: 
    -version print version information and exit 
    dev=target SCSI target to use as CD/DVD-Recorder 
    gracetime=# set the grace time before starting to write to #. 
... 

如果您有輸出到標準輸出和標準錯誤的命令,你想合併它們,你可以做到這一點通過管道錯誤輸出到標準輸出,然後抓住標準輸出。

subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 

正如Chris Morgan提到的,你應該用proc.communicate()代替proc.read()

>>> proc = subprocess.Popen(['cdrecord', '--help'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) 
>>> out, err = proc.communicate() 
>>> print 'stdout:', out 
stdout: 
>>> print 'stderr:', err 
stderr:Usage: wodim [options] track1...trackn 
Options: 
    -version print version information and exit 
    dev=target SCSI target to use as CD/DVD-Recorder 
    gracetime=# set the grace time before starting to write to #. 
... 
+0

好吧,這適用於'ls',但後來我遇到了一個不同的問題,當試圖運行一個不同的命令。當我嘗試使用該方法運行「cdrecord --help」時,出現跟蹤錯誤。 – Insomaniacal 2010-12-23 00:04:47

+0

@Insomaniacal查看編輯 – marcog 2010-12-23 00:12:52

8

隨着a = subprocess.Popen("cdrecord --help",stdout = subprocess.PIPE) ,你需要或者使用列表,或使用shell=True;

其中任何一個都可以。前者是可取的。

a = subprocess.Popen(['cdrecord', '--help'], stdout=subprocess.PIPE) 

a = subprocess.Popen('cdrecord --help', shell=True, stdout=subprocess.PIPE) 

而且,而是採用Popen.stdout.read/Popen.stderr.read,你應該使用.communicate()(參見子文檔爲什麼)。

proc = subprocess.Popen(['cdrecord', '--help'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) 
stdout, stderr = proc.communicate() 
22

如果您使用python 2.7或更高版本,最簡單的方法是使用subprocess.check_output()命令。這裏有一個例子:

output = subprocess.check_output('ls') 

要同時重定向標準錯誤,你可以使用以下命令:

output = subprocess.check_output('ls', stderr=subprocess.STDOUT) 



在要參數傳遞給該命令的情況下,你可以使用一個列表或使用調用一個shell並使用一個字符串。

output = subprocess.check_output(['ls', '-a']) 
output = subprocess.check_output('ls -a', shell=True)