2014-07-18 30 views
1

嗨,我是一名Python初學者,並且喜歡通過Python的子流程模塊執行shell命令。 但是對於Popen構造函數有一些疑問 關於:參數stdin和stdout無法理解Python中的stdin和stdout如何在Python中工作

考慮我正在執行腳本來ping一個網站。順其自然 「www.google.com」 通過shell命令

項目#1:

import sys 
import subprocess 
cmdping = "ping -c4 www.google.com"  
p = subprocess.Popen(cmdping,shell=True,stdout=subprocess.PIPE,universal_newlines=True) 
while True: 
    out= p.stdout.read(1) 
    if out == '' and p.poll() != None: 
     break 
    if out != '': 
     sys.stdout.write(out) 
     sys.stdout.flush() 
  1. 究竟發生在標準輸出= subprocess.PIPE.If我是對的,stdout是標準輸出。 那麼,爲什麼我們使用了= p.stdout.read(1)

如果我的計劃是像

import sys 
import subprocess 
cmdping = "ping -c4 10.10.22.20" 
p = subprocess.Popen(cmdping, shell=True,stdin=subprocess.PIPE,universal_newlines=True) 

,輸出類似:

PING 10.10.22.20 (10.10.22.20) 56(84) bytes of data. 

64 bytes from 10.10.22.20: icmp_seq=1 ttl=63 time=0.951 ms 

UMR-AUTO [email protected] #64 bytes from 10.10.22.20: icmp_seq=2 ttl=63 time=0.612 ms 

64 bytes from 10.10.22.20: icmp_seq=3 ttl=63 time=0.687 ms 

64 bytes from 10.10.22.20: icmp_seq=4 ttl=63 time=0.638 ms 



--- 10.10.22.20 ping statistics --- 

4 packets transmitted, 4 received, 0% packet loss, time 3002ms 

rtt min/avg/max/mdev = 0.612/0.722/0.951/0.134 ms 

你能解釋我這個請嗎?

我無法理解過程如何發生並想要準確知道。

回答

1

A pipe是一種流程可以鏈接在一起的方式,以便它們可以使用標準流進行通信。下面是介紹各種管道的示意圖和如何使用它們從維基百科:

Pipe Diagram from Wikipedia

這意味着,你可以採取一個過程的輸出,並把它作爲另一個進程的輸入,並把這些過程連在一起。

有三個主要區域可以插入管道。標準輸出(stdout),標準輸入(stdin)和標準錯誤(stderr)流。

這使您可以將輸出重定向到其他應用程序。例如,您可能希望將所有錯誤輸出重定向到將此輸出發送到數據庫的程序。

現在,當你想從自己的程序中執行一個進程時,你必須決定如何與它進行通信。但是,大多數情況下可以使用許多便利方法。這些使用下面的管道,但他們提供了一個友好的界面。

  1. 最簡單的情況是,當你只是想運行一個進程,而你關心的只是運行成功與否。對於這一點,你用subprocess.call

    if subprocess.call(['ping', '-c', '1', 'www.google.com']) != 0: 
        print('There was an error') 
    

    還有subprocess.check_call。他們都做同樣的事情,唯一的區別是check_call將引發CallProcessError例外,如果有問題。您可以捕獲並輸出錯誤消息。

  2. 你想運行一個命令,並搶輸出,用於此用途subprocess.check_output

    try: 
    
        result = subprocess.check_output(['ping', '-c', '1', 'www.google.com']) 
        print('The result is: {}'.format(result)) 
    
    except subprocess.CallProcessError, e: 
        print('There was an error: {}'.format(e)) 
    

    下面是它會返回:

    >>> result = subprocess.check_output(['ping', '-c', '1', 'www.google.com']) 
    >>> print(result) 
    PING www.google.com (78.159.164.59) 56(84) bytes of data. 
    64 bytes from 78.159.164.59: icmp_seq=1 ttl=49 time=33.4 ms 
    
    --- www.google.com ping statistics --- 
    1 packets transmitted, 1 received, 0% packet loss, time 0ms 
    rtt min/avg/max/mdev = 33.414/33.414/33.414/0.000 ms 
    
  3. 運行的過程,然後把它一些其他命令。爲此,您使用Popen.communicate和管道。

    爲了能夠與流程進行通信,您需要創建一個管道,然後在程序中獲取該管道的句柄。

    如果你只想發送命令,您將創建一個管道stdin,如果你想發送命令,然後讀取結果 - 你需要創建一個點子既stdinstdout(也可使用標準錯誤)。

    在這個例子中,從Python外殼我們推出另一個Python外殼,然後執行import this和閱讀的結果:

    >>> handle = subprocess.Popen(['python'], 
               stdin=subprocess.PIPE, 
               stderr=subprocess.PIPE, 
               stdout=subprocess.PIPE, shell=True) 
    >>> result, error = handle.communicate('import this') 
    >>> print(result) 
    The Zen of Python, by Tim Peters 
    
    Beautiful is better than ugly. 
    Explicit is better than implicit. 
    Simple is better than complex. 
    Complex is better than complicated. 
    Flat is better than nested. 
    Sparse is better than dense. 
    Readability counts. 
    Special cases aren't special enough to break the rules. 
    Although practicality beats purity. 
    Errors should never pass silently. 
    Unless explicitly silenced. 
    In the face of ambiguity, refuse the temptation to guess. 
    There should be one-- and preferably only one --obvious way to do it. 
    Although that way may not be obvious at first unless you're Dutch. 
    Now is better than never. 
    Although never is often better than *right* now. 
    If the implementation is hard to explain, it's a bad idea. 
    If the implementation is easy to explain, it may be a good idea. 
    Namespaces are one honking great idea -- let's do more of those! 
    

最後,你會發現,我傳遞一個列表,我的命令。這是列出要啓動的命令(及其選項)的推薦方式。

可以使用shlex模塊,以幫助你打破一個命令串到它的各個組成部分:

>>> import shlex 
>>> cmd = 'ping -c1 google.com' 
>>> parsed_cmd = shlex.split(cmd) 
>>> parsed_cmd 
['ping', '-c1', 'google.com'] 

這是一個簡單的例子,但documentation顯示了更復雜的例子。

+0

嗨,非常感謝回覆。但是這個「handle.communicate('導入這個')」是什麼意思。通常Popen.communicate用於與流程進行交流並獲取流程的輸出。但是這個「import this」看起來很奇怪,我們也得到了這個輸出 – user3275349

+0

'import this'是我發送給這個進程的命令。 '.communicate()'是一個雙向通道。沒有任何參數'handle.communicate()'你會得到結果。 –

+0

我想這從SYS進口* 進口子 手柄= subprocess.Popen([ '蟒'], 標準輸入= subprocess.PIPE, 標準錯誤= subprocess.PIPE, 標準輸出= subprocess.PIPE,殼=真) 結果,錯誤= handle.communicate() 打印(結果),但它顯示空輸出 – user3275349