日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

【Python】 子进程创建与使用subprocess

發布時間:2023/11/30 python 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Python】 子进程创建与使用subprocess 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

subprocess

*****本文參考了Vamei大神的http://www.cnblogs.com/vamei/archive/2012/09/23/2698014.html  

 運用subprocess包可以在運行python的進程下進一步開啟一個子進程,創建子進程要注意

    1. 父進程是否暫停

    2.創建出的子進程返回了什么

    3.執行出錯,即返回的code不是0的時候應該如何處理

  subprocess包提供了三個開啟子進程的方法,subprocess.call() , subprocess.check_call() , subprocess.check_output(),給三者傳遞命令字符串作為參數。可以用(['ping','www.baidu.com','-c','3'])這種列表的形式,同時也可以是("ping www.baidu.com -c 3") 這種形式。在開啟子進程的時候,可以加上shell=True的參數來讓python開啟一個shell,通過shell來解釋獲得的命令。一般在windows下運行的程序最好都把shell=True加上,這樣才能順利地執行dos命令,但是linux下似乎不加也沒啥關系。因為linux下未指明用shell執行的話會調用/bin/sh來執行,問題不大,但是dos下系統不會默認用cmd.exe來執行命令,所以要加上shell=True。

  subprocess.call ; subprocess.check_call ; subprocess.check_output? 這三者的區別在于,返回的值分別是,子進程的執行返回碼;若返回碼是0則返回0,否則出錯的話raise起CalledProcessError,可以用except處理之;若返回碼是0則返回子進程向stdout輸出的結果,否則也raise起CalledProcessError。另外,這三個方法都是讓父進程掛起等待的,在子進程結束之前,父進程不會繼續往下運行。

  另外從本質上講,上述三個方法都是對subprocess.Popen方法的一個包裝,Popen開啟的子進程是不會讓父進程等待其完成的,除非調用了wait()方法:

child = subprocess.Popen("...",shell=True) print "Hello" """ 很可能hello在子進程的輸出之前就被打印出來了,因為父進程不等child子進程運行完 """child = subprocess.Popen("...",shell=True) child.wait() print "Hello" """ 這就不一樣,父進程一定會等子進程運行完,給出完整的結果之后再繼續往下執行。相當于wait函數掛起了父進程。 """

?  此外,上面代碼里的child這個對象還有其他的一些方法:

    child.poll()  返回子進程運行狀態,主要是兩種結果,None代表尚未運行完,而一個返回碼則代表已經運行完成并且是成功或失敗了

    child.kill()  強行終止子進程

    child.send_signal(...)  向子進程發送一個信號(具體信號是以什么方式表示不清楚,還待研究

    child.terminate()  終止子進程

    child.pid  子進程的pid

    child.returncode  子進程的返回碼

    child.stdin/stdout/stderr    子進程的標準輸入流,標準輸出和標準錯誤輸出,都是類文件對象

?

■  文本流控制

  每個子進程對象都有stdin/stdout/stderr三個對象,而在Popen開啟子進程的時候,可以設置這三個對象。比如

child1 = subprocess.Popen("cmd1",shell=True, stdout=subprocess.PIPE) ''' child1的stdout被設置成管道,可以把它理解成一個第三方托管機構, 因為不設置的話child1的stdout的內容就直接被打印到父進程的stdout里了, 設置成管道之后內容被導入了PIPEという名の第三方托管機構里 ''' child2 = subprocess.Popen("cmd2",shell=True,stdin=child1.stdout,stdout=subprocess.PIPE) ''' 把child2的stdin設置成了child1的stdout,也就是之前那個第三方機構,這么一來就實現了兩個子進程之間的數據通信了。
而把child2的stdout也設置成第三方,是因為不想讓child2的輸出就直接這么輸出到父進程的stdout里,而要對它做一些處理
''' stdout,tmp = child2.communicate() ''' 因為child2的輸出不用再轉給個child3去處理,就用communicate方法把第三方機構那里的數據取出來放進一個變量里。
注意,這里的stdout已經是個str對象了,communicate出來的都是字符串了
communicate方法自帶wait功能,會讓父進程掛起等待所有子進程結束
communicate會返回一個元組,但是像在這個例子中沒有設置stderr=PIPE,所以元組中的第二項原本屬于stderr的值的地方的tmp的值是None,如果設置了其為PIPE,由于沒有錯誤信息tmp是""。這點是有區別的。
''' print "We have result:\n%s"%(stdout) #代表了把stdout做一些處理后再輸出

?

?■  Popen方法

  Popen就是開啟一個新的子進程,常用的幾個參數正如上面所提的cmd,shell,stdin,stdout,stderr來指定開啟的子進程的一些屬性。

  除此之外還有以下的參數:

    close_fds  默認為False,設置為True的情況下會在子進程執行之前關閉所有除了0,1,2之外的所有文件都關閉(雖然不知道有什么意義)

    cwd  默認None,可以為子進程設置工作目錄

  盜了張圖(http://www.cnblogs.com/zhoug2020/p/5079407.html)

  

?

  實際上,我一般都是這么干的:

import subprocessp = subprocess.Popen("CMD",shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE) stdout,stderr = p.communicate() if stderr != "":print "ERROR:"+stderr elseprint "RESULT:"+stdout

?

*這篇文章(http://www.tuicool.com/articles/bUNJ7v)提供了一個解決大量并發開啟子進程時出bug的方案,同時也給了一個如何為一個子進程設置超時的方法,值得看一下:

def timeout_command(command, timeout):start = datetime.datetime.now()process = subprocess.Popen(command, bufsize=10000, stdout=subprocess.PIPE, close_fds=True)'''這個循環就是為子進程設置了超時功能,感覺還挺巧妙的。。'''while process.poll() is None:time.sleep(0.1)now = datetime.datetime.now()if (now - start).seconds> timeout:try:process.terminate()except Exception,e:return Nonereturn Noneout = process.communicate()[0]if process.stdin:process.stdin.close()if process.stdout:process.stdout.close()if process.stderr:process.stderr.close()try:process.kill()except OSError:passreturn out

?■  關于實時獲取子進程輸出的方法

  之前用過的所有subprocess.Popen方法吧,打開的子進程都比較短小,其命令基本上都可以在一秒內完成。所以在communicate的時候都沒有顯示出什么不妥的地方。但是碰到一些比較大,運行時間比較長的命令時,communicate就顯得有些不太好了,因為到命令運行完成或者緩沖區滿為止,子進程對象是不會向程序返回輸出內容的。此時就需要變通一點不要使用communicate了。

  一個解決的辦法是這樣的:

import subprocess import sysp = subprocess.Popen('cmd',shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)while p.poll() is None: #當子進程沒有完成之前char = p.stdout.read(1)sys.stdout.write(char)stdout,stderr = p.communicate() sys.stdout.write(stdout)

?

  觀察這段程序,可以看到,當子進程沒有結束之前,循環將不斷地從子進程的stdout中讀取一個字符的數據然后寫到父進程的stdout中。如果子進程較長時間沒有明文進入stdout的話也可以在循環中加上一個time.sleep來控制循環頻率。下面再加上communicate是為了保證信息輸出的完整性。因為當子進程結束之后,有可能stdout還沒有讀取光,如果不加communicate的話那么還剩余在stdout中的信息就丟失了。如果子進程在stderr中有輸出那么也可以放在communicate后面判斷。另外也可以在建立p對象的時候把stderr參宿設置為subprocess.STDOUT來把子進程的stderr輸出重定向到stdout中。

  *測試的時候,把一個每sleep1秒就向stdout寫入一些信息的腳本當做子進程。但是發現以上方法并不奏效。想了下之后,記起來python在寫文件的時候是會有緩沖區這個設定的。也就是說,子進程代碼中的write被調用后stdout并不馬上把信息輸出到stdout中。解決辦法就是用file對象(這里是sys.stdout)調用flush()方法來清空緩存并寫入文件。

?

轉載于:https://www.cnblogs.com/franknihao/p/6537159.html

總結

以上是生活随笔為你收集整理的【Python】 子进程创建与使用subprocess的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。