【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

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/393542.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/393542.shtml
英文地址,請注明出處:http://en.pswp.cn/news/393542.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

異步查詢回調函數調用

異步查詢數據,需要對返回的數據進行后續步驟操作,使用使用方法: 1、new promise方法使用。 2、回調函數使用 使用方式:   pageGetDeviceTreeInfo({deviceTypeAry:[1]},this.getTreeData); 函數: 1 export function p…

前端開發從項目中獲得什么_我如何獲得副項目的前10個客戶以及從他們那里學到的東西...

前端開發從項目中獲得什么by Tigran Hakobyan由Tigran Hakobyan 我如何獲得副項目的前10個客戶以及從他們那里學到的東西 (How I got my first 10 customers for my side-project and what I’ve learned from them) My name is Tigran, I’m 29, and I’m the creator of Cro…

leetcode278. 第一個錯誤的版本(二分查找)

你是產品經理,目前正在帶領一個團隊開發新的產品。不幸的是,你的產品的最新版本沒有通過質量檢測。由于每個版本都是基于之前的版本開發的,所以錯誤的版本之后的所有版本都是錯的。 假設你有 n 個版本 [1, 2, …, n],你想找出導致…

lrzsz ??linux與windows互傳

2019獨角獸企業重金招聘Python工程師標準>>> lrzsz linux與windows互傳 # 前提是使用 xshell 或者 securecrt 這兩個遠程軟件,putty不支持 yum install -y lrzsz //安裝文件包 linux向windows 傳文件使用 : sz 文件名 回…

mysql show 命令_mysql show 相關命令

processlist的show方式是不能使用過濾查找,可能源自MySQL的內部安全機制吧,show是用來查看MySQL內部運行數據,其實processlist就是information_schema數據庫中的一張表,那么通過查表的方式肯定是可以的了:SELECT user,…

ordereddict有序字典

import collections as con# 有序添加和取字典元素 ord con.OrderedDict() ord[a] 1 ord[b] 2 ord[c] 3 print(ord, ordereddict)# 移動某元素到最后 ord.move_to_end(a) print(ord, move_to_end)轉載于:https://www.cnblogs.com/xh4528/p/6538700.html

Spring: (一) -- 春雨潤物之 核心IOC

作為一個Java人,想必都或多或少的了解過Spring。對于其優勢也能道個一二,諸如方便解耦、支持AOP編程、支持聲明式事務、方便測試等等。Spring也不僅僅局限于服務器端開發,它可以做非常多的事情,任何Java應用都可以在簡單性、可測試…

reactjs快速如夢_幫助您理解和創建ReactJS應用的快速指南

reactjs快速如夢此帖子分為2部分 (This Post is divided into 2 parts) The First Part demonstrates how to create a simple React app using ‘create-react-app’ CLI and explains the project structure. 第一部分演示了如何使用“ create-react-app” CLI創建簡單的Reac…

leetcode1351. 統計有序矩陣中的負數(二分查找)

給你一個 m * n 的矩陣 grid,矩陣中的元素無論是按行還是按列,都以非遞增順序排列。 請你統計并返回 grid 中 負數 的數目。 示例 1: 輸入:grid [[4,3,2,-1],[3,2,1,-1],[1,1,-1,-2],[-1,-1,-2,-3]] 輸出:8 解釋&a…

XUbuntu22.04之跨平臺音頻編輯工具(平替Audition):ocenaudio(二百零二)

加粗樣式 簡介: CSDN博客專家,專注Android/Linux系統,分享多mic語音方案、音視頻、編解碼等技術,與大家一起成長! 優質專欄:Audio工程師進階系列【原創干貨持續更新中……】🚀 優質專欄&#…

QueryList4采集-圖片本地化

QueryList4采集圖片本地化 //采集public function cai() {//采集的url地址$data QueryList::get(https://news.ke.com/sh/baike/0033/)->rules([title > [.LOGCLICK , text],content > [.summary , text],image > [.lj-lazy , data-original , ,function($res){//…

mysql 從服務器同步設置_mysql主從同步配置

1.為什么要主從同步?在Web應用系統中,數據庫性能是導致系統性能瓶頸最主要的原因之一。尤其是在大規模系統中,數據庫集群已經成為必備的配置之一。集群的好處主要有:查詢負載、數據庫復制備份等。其中Master負責寫操作的負載&…

int、long、long long取值范圍

short int 1個字節儲存 unsigned short int 0~255short int -128~127 int 2個字節儲存 unsigned int 0~4294967295 int 2147483648~2147483647 long 4個字節儲存 unsigned long 0~4294967295long 21…

每天一個LINUX命令(pwd)

每天一個LINUX命令(pwd) 基本信息 pwd: /bin/pwd,顯示當前路徑的絕對路徑 語法:pwd 應用程序位置 which pwd PWD作用 pwd --help或者man pwd PWD的使用 pwd 轉載于:https://www.cnblogs.com/shanshanliu/p/6542403.html

leetcode69. x 的平方根(二分法)

實現 int sqrt(int x) 函數。 計算并返回 x 的平方根,其中 x 是非負整數。 由于返回類型是整數,結果只保留整數的部分,小數部分將被舍去。 示例 1: 輸入: 4 輸出: 2 代碼 class Solution {public int mySqrt(int x) {int l0,rx;while (…

一個swiper 兩個分頁器的寫法【總結】

寫項目的時候&#xff0c;使用的是swiper插件呈現的效果是一個swiper要實現兩個分頁器&#xff0c;下面就來總結一下 以swiper3為例來寫&#xff0c;在頁面中引入jquery、swiper.min.js和swiper.min.css文件。 HTML結構&#xff1a; <div class"banner swiper-containe…

react路由守衛+重定向_React + Apollo:如何在重新查詢后進行重定向

react路由守衛重定向by Jun Hyuk Kim金俊赫 React Apollo&#xff1a;如何在重新查詢后進行重定向 (React Apollo: How to Redirect after Refetching a Query) GraphQL is hot, and for a good reason. In short, it is a query language that allows you to ask for exact…

python 爬蟲可視化編程_Python爬蟲爬取博客實現可視化過程解析

源碼&#xff1a;from pyecharts import Barimport reimport requestsnum0b[]for i in range(1,11):linkhttps://www.cnblogs.com/echoDetected/default.html?pagestr(i)headers{user-agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko…

tp6常用命令

TP6常用命令 1.創建控制器 php think make:controller --plain index** (php think make:controller --plain 控制器名稱&#xff08;首字母大寫&#xff09;)2.創建模型 php think make:model 【模塊名】/模型名 模型名為表名相當3.創建中間件 php think make:middleware 中…

Problem B: 字符類的封裝

Description 先來個簡單習題&#xff0c;練練手吧&#xff01;現在需要你來編寫一個Character類&#xff0c;將char這一基本數據類型進行封裝。該類中需要有如下成員函數&#xff1a; 1. 無參構造函數。 2. 構造函數Character(char)&#xff1a;用參數初始化數據成員。 3. void…