欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Python中subprocess模塊的用法詳解

 更新時間:2023年08月23日 09:27:07   作者:polyhedronx  
這篇文章主要介紹了Python中subprocess模塊的用法詳解,subprocess是Python 2.4中新增的一個模塊,它允許你生成新的進(jìn)程,連接到它們的 input/output/error 管道,并獲取它們的返回狀態(tài)碼,這個模塊的目的在于替換幾個舊的模塊和方法,需要的朋友可以參考下

Python subprocess模塊

subprocess是用于啟動進(jìn)程,并與進(jìn)程通信的模塊。

格式

該模塊定義了一個Popen類:

class Popen(args, bufsize=0, executable=None,
            stdin=None, stdout=None, stderr=None,
            preexec_fn=None, close_fds=False, shell=False,
            cwd=None, env=None, universal_newlines=False,
            startupinfo=None, creationflags=0):

參數(shù)釋義:

args  

應(yīng)該是字符串或程序參數(shù)序列,要執(zhí)行的程序通常是args序列或字符串中的第一項,但可以使用
executable參數(shù)顯式設(shè)置。

在UNIX 上,當(dāng) shell=False(默認(rèn)), 類Popen 用 os.execvp() 來執(zhí)行子程序,args通常應(yīng)該是一個序列,如果args是一個字符串,它也會被視為只有一個元素的序列。

在UNIX 上,當(dāng) shell=True,如果 args 是字符串,它將作為命令行字符串通過shell 執(zhí)行;如果是一個序列,它的第一項將作為命令行字符串,其他項將被視為附加的shell參數(shù)。

在 Windows 上,類Popen 用 CreateProcess() 來執(zhí)行子程序,它以字符串作為參數(shù)。

如果args是一個序列,它將使用 list2cmdline 方法轉(zhuǎn)換為字符串。需要注意的是,并非所有MS Windows應(yīng)用程序都以相同的方式解釋命令行,list2cmdline 是為使用與MS C運行規(guī)則相同的應(yīng)用程序而設(shè)計的。

bufsize 

如果被賦值,值將作為內(nèi)建函數(shù) open() 的參數(shù),0意味著無緩沖,1就是行緩沖,任何其他正值意味著使用與該值大小接近的緩沖區(qū)。負(fù)bufsize意味著使用系統(tǒng)默認(rèn)值,這通常意味著完全緩沖。 bufsize的默認(rèn)值為0(無緩沖)。

stdin, stdout and stderr 

分別代表子程序的標(biāo)準(zhǔn)輸入,標(biāo)準(zhǔn)輸出,標(biāo)準(zhǔn)錯誤輸出的文件句柄。

有效值為PIPE、現(xiàn)有文件描述符(正整數(shù))、現(xiàn)有文件對象和None。若賦值為PIPE ,就會為子程序創(chuàng)建新管道 ;若為None,不會發(fā)生重定向,子程序的文件句柄將從父程序繼承。

另外,stderr可以是STDOUT,這表明子程序的錯誤數(shù)據(jù)可以被獲得并發(fā)送到stdout輸出。

 preexec_fn 如果preexec_fn設(shè)置為可調(diào)用對象,則在執(zhí)行子進(jìn)程之前,將在子進(jìn)程中調(diào)用此對象。

close_fds 若為true,則在執(zhí)行子進(jìn)程之前將關(guān)閉除0,1和2之外的所有文件描述符。

shell 若為true,則將通過shell執(zhí)行指定的命令。

cwd 若不是None,在執(zhí)行子進(jìn)程之前,當(dāng)前目錄將更改為cwd。

env 若不是None,它將為新進(jìn)程指定環(huán)境變量。

universal_newlines 文件對象stdout和stderr作為文本文件打開,但可以通過 '\n' (Unix), '\r' (Mac), '\r\n' (Win)斷行。所有這些外部表示都被Python程序視為'\n'。注意:僅當(dāng)Python使用通用換行支持(默認(rèn))構(gòu)建時,此功能才可用。注意這些特征只在python支持通用換行的時候有效(默認(rèn)支持)。

此外,communication() 方法不會更新文件對象stdout,stdin和stderr的換行屬性。

startupinfo, creationflags 如果給定,將傳遞給底層的 CreateProcess() 函數(shù)。它可以指定主窗口的外觀和新進(jìn)程的優(yōu)先級等內(nèi)容。(僅限Windows)

該模塊還定義了兩個快捷功能:

call(*args, **kwargs):

使用參數(shù)運行命令。等待命令完成,然后返回returncode屬性。

參數(shù)與Popen構(gòu)造函數(shù)相同。例:

retcode = call(["ls", "-l"])

異常

在新程序開始執(zhí)行之前,子進(jìn)程中引發(fā)的異常將在父進(jìn)程中重新引發(fā)。此外,異常對象將有一個名為'child_traceback'的額外屬性,該屬性是一個包含來自子進(jìn)程視點的回溯信息的字符串。

引發(fā)的最常見異常是OSError。例如,在嘗試執(zhí)行不存在的文件時會發(fā)生這種情況。應(yīng)用程序應(yīng)當(dāng)對OSErrors作出處理。

如果使用無效參數(shù)調(diào)用Popen,則會引發(fā)ValueError。

安全性

與其他一些 popen 函數(shù)不同,此實現(xiàn)永遠(yuǎn)不會隱式調(diào)用/bin/sh。

這意味著所有字符(包括shell元字符)都可以安全地傳遞給子進(jìn)程。

Popen 對象

Popen類的實例具有以下方法:

Popen.poll():

檢查子進(jìn)程是否已終止。終止則返回returncode屬性;否則,返回None。

Popen.wait(timeout=None):

等待子進(jìn)程終止,返回returncode屬性。

如果進(jìn)程在超時秒后沒有終止,則引發(fā) TimeoutExpired 異常。捕獲此異常并重試等待將會更安全。

注意:當(dāng)使用stdout = PIPE或stderr = PIPE,并且子進(jìn)程生成太多輸出以致于阻止了等待OS管道緩沖區(qū)接受更多數(shù)據(jù)時,將導(dǎo)致死鎖。使用管道時可以使用 Popen.communicate() 來避免這種情況。

注意:該功能使用忙循環(huán)(非阻塞呼叫和短暫睡眠)實現(xiàn)。

在Python3.3中添加了timeout參數(shù)。

從Python3.4開始不推薦使用endtime參數(shù)。這是無意中暴露在3.3中,但沒有記錄,因為它是私人內(nèi)部使用。請改用timeout 。

Popen.communicate(input=None, timeout=None):

與進(jìn)程交互:將數(shù)據(jù)發(fā)送到stdin。從stdout和stderr讀取數(shù)據(jù),直到達(dá)到文件結(jié)尾。等待進(jìn)程終止??蛇x的input參數(shù)應(yīng)該是要發(fā)送到子進(jìn)程的數(shù)據(jù),如果沒有數(shù)據(jù)需要發(fā)送給子進(jìn)程,則設(shè)為None。如果在文本(text)模式下打開流,則input參數(shù)必須是字符串(string);否則,它必須是字節(jié)(bytes)。

communic()返回一個 tuple(stdout_data, stderr_data) 。如果在文本模式下打開流,則數(shù)據(jù)將是字符串;否則,是字節(jié)。

注意:如果要將數(shù)據(jù)發(fā)送到進(jìn)程的stdin,則需要使用stdin = PIPE創(chuàng)建Popen對象。同樣,要在結(jié)果元組(tuple)中獲取除None之外的任何內(nèi)容,還需要設(shè)置stdout = PIPE and/or stderr = PIPE。

如果進(jìn)程在超時(timeout)秒后沒有終止,則會引發(fā)TimeoutExpired異常。捕獲此異常并重試通信不會丟失任何輸出。

如果超時到期,則子進(jìn)程不會被終止,因此為了正確清理,行為良好的應(yīng)用程序應(yīng)該終止子進(jìn)程并完成通信:

proc = subprocess.Popen(...)
try:
    outs, errs = proc.communicate(timeout=15)
except TimeoutExpired:
    proc.kill()
    outs, errs = proc.communicate()

注意:讀取的數(shù)據(jù)緩沖在內(nèi)存中,因此如果數(shù)據(jù)大小很大或不受限制,請不要使用此方法。

在Python3.3中添加了timeout參數(shù)。

Popen.send_signal(signal):

向子進(jìn)程發(fā)送signal信號。

注意:在 Windows 上,SIGTERM和terminate() 的作用相同??梢詫?CTRL_C_EVENTCTRL_BREAK_EVENT 發(fā)送到使用 creationflags 參數(shù)啟動的進(jìn)程,該參數(shù)包括 CREATE_NEW_PROCESS_GROUP 。

Popen.terminate():

終止(stop)子進(jìn)程。在Posix OSs上,該方法將SIGTERM發(fā)送給子進(jìn)程。在Windows上,調(diào)用Win32 API函數(shù)TerminateProcess() 來停止子進(jìn)程。

Popen.kill():

殺死子進(jìn)程。在Posix OSs上,該方法將 SIGKILL 發(fā)送給子進(jìn)程。在Windows上,kill() 和terminate() 的作用相同。

還提供以下屬性:

Popen.args:

args參數(shù)傳遞給Popen 程序參數(shù)序列或單個字符串。

Python3.3中的新功能。

Popen.stdin:

如果stdin參數(shù)是PIPE,則此屬性是open() 返回的可寫流對象。如果指定了encoding或errors參數(shù)或者universal_newlines參數(shù)為True,則流是文本流,否則它是字節(jié)流。如果stdin參數(shù)不是PIPE,則此屬性為None。

obj.stdin.write(" args ")

Popen.stdout:

如果stdout參數(shù)是PIPE,則此屬性是open() 返回的可讀流對象。從流中讀取提供子進(jìn)程的輸出。如果指定了encoding或errors參數(shù)或者universal_newlines參數(shù)為True,則流是文本流,否則它是字節(jié)流。如果stdout參數(shù)不是PIPE,則此屬性為None。

obj.stdout.read() 

Popen.stderr:

如果stderr參數(shù)是PIPE,則此屬性是open() 返回的可讀流對象。從流中讀取提供子進(jìn)程的錯誤輸出。如果指定了encoding或errors參數(shù)或者universal_newlines參數(shù)為True,則流是文本流,否則它是字節(jié)流。如果stderr參數(shù)不是PIPE,則此屬性為None。

警告:使用 communic() 而不是 .stdin.write,.stdout.read 或 .stderr.read 來避免由于任何其他OS管道緩沖區(qū)填滿和阻止子進(jìn)程而導(dǎo)致的死鎖。

Popen.pid:

子進(jìn)程的進(jìn)程ID。

注意:如果將shell參數(shù)設(shè)置為True,則這是生成的shell的進(jìn)程ID。

Popen.returncode:

子進(jìn)程返回碼,由poll() 和wait() 設(shè)置(間接通過communic())。 None 表示該進(jìn)程尚未終止,負(fù)值 N 表示子進(jìn)程被信號 N 終止(僅限POSIX)。

  • returncode=0 表示執(zhí)行成功
  • returncode=127 表示語句為空串
  • returncode=17 表示找不到表
  • returncode=64 表示缺失關(guān)鍵字
  • returncode=41 表示查詢的字段不存在

例如:

import os
import shlex
import signal
import subprocess
shell_cmd = 'ping www.baidu.com'
cmd = shlex.split(shell_cmd)
p = subprocess.Popen(cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
# ***CTRL_C信號***
# os.kill(p.pid, signal.CTRL_C_EVENT)
# p.send_signal(signal.CTRL_C_EVENT)
# ***SIGTERM信號***
# p.send_signal(signal.SIGTERM)
# p.terminate()
# p.kill()
while p.poll() is None:  # 當(dāng)子進(jìn)程未終止
	line = p.stdout.readline().decode('gbk').strip()
	print(line)
if p.returncode == 0:
	print('Subprogram success')
else:
	print('Subprogram failed')
 

用 subprocess 模塊替換舊函數(shù)

在本節(jié)中,“a ==> b”表示a可以被b替代。

注意:如果找不到執(zhí)行的程序,則本節(jié)中的所有函數(shù)都會或多或少的調(diào)用失敗。此模塊引發(fā)OSError異常。

在以下示例中,我們假設(shè) subprocess 模塊使用 from subprocess import * 導(dǎo)入。

替換/bin/sh shell反引號

output=`mycmd myarg`
==>
output = Popen(["mycmd", "myarg"], stdout=PIPE).communicate()[0]

替換shell管道

output=`dmesg | grep hda`
==>
p1 = Popen(["dmesg"], stdout=PIPE)
p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
output = p2.communicate()[0]

替換os.system()

sts = os.system("mycmd" + " myarg")
==>
p = Popen("mycmd" + " myarg", shell=True)
sts = os.waitpid(p.pid, 0)

注意:

  • 通常不需要通過shell調(diào)用程序。
  • 查看returncode屬性比退出狀態(tài)更容易。

一個更實際的例子:

try:
    retcode = call("mycmd" + " myarg", shell=True)
    if retcode < 0:
        print >>sys.stderr, "Child was terminated by signal", -retcode
    else:
        print >>sys.stderr, "Child returned", retcode
except OSError, e:
    print >>sys.stderr, "Execution failed:", e

替換os.spawn*

P_NOWAIT示例:

pid = os.spawnlp(os.P_NOWAIT, "/bin/mycmd", "mycmd", "myarg")
==>
pid = Popen(["/bin/mycmd", "myarg"]).pid

P_WAIT示例:

retcode = os.spawnlp(os.P_WAIT, "/bin/mycmd", "mycmd", "myarg")
==>
retcode = call(["/bin/mycmd", "myarg"])

Vector示例:

os.spawnvp(os.P_NOWAIT, path, args)
==>
Popen([path] + args[1:])

Environment示例:

os.spawnlpe(os.P_NOWAIT, "/bin/mycmd", "mycmd", "myarg", env)
==>
Popen(["/bin/mycmd", "myarg"], env={"PATH": "/usr/bin"})

替換os.popen*

pipe = os.popen(cmd, mode='r', bufsize)
==>
pipe = Popen(cmd, shell=True, bufsize=bufsize, stdout=PIPE).stdout
pipe = os.popen(cmd, mode='w', bufsize)
==>
pipe = Popen(cmd, shell=True, bufsize=bufsize, stdin=PIPE).stdin
(child_stdin, child_stdout) = os.popen2(cmd, mode, bufsize)
==>
p = Popen(cmd, shell=True, bufsize=bufsize,
          stdin=PIPE, stdout=PIPE, close_fds=True)
(child_stdin, child_stdout) = (p.stdin, p.stdout)
(child_stdin,
 child_stdout,
 child_stderr) = os.popen3(cmd, mode, bufsize)
==>
p = Popen(cmd, shell=True, bufsize=bufsize,
          stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True)
(child_stdin,
 child_stdout,
 child_stderr) = (p.stdin, p.stdout, p.stderr)
(child_stdin, child_stdout_and_stderr) = os.popen4(cmd, mode, bufsize)
==>
p = Popen(cmd, shell=True, bufsize=bufsize,
          stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True)
(child_stdin, child_stdout_and_stderr) = (p.stdin, p.stdout)

替換popen2.*

注意:如果popen2函數(shù)的cmd參數(shù)是一個字符串,則該命令通過 /bin/sh 執(zhí)行。如果是列表,則直接執(zhí)行該命令。

(child_stdout, child_stdin) = popen2.popen2("somestring", bufsize, mode)
==>
p = Popen(["somestring"], shell=True, bufsize=bufsize
          stdin=PIPE, stdout=PIPE, close_fds=True)
(child_stdout, child_stdin) = (p.stdout, p.stdin)
(child_stdout, child_stdin) = popen2.popen2(["mycmd", "myarg"], bufsize, mode)
==>
p = Popen(["mycmd", "myarg"], bufsize=bufsize,
          stdin=PIPE, stdout=PIPE, close_fds=True)
(child_stdout, child_stdin) = (p.stdout, p.stdin)

popen2.Popen3 和 popen3.Popen4 基本上用作subprocess.Popen,除了:

subprocess.Popen如果執(zhí)行失敗則引發(fā)異常。

capturestderr參數(shù)被替換為stderr參數(shù)。

必須指定stdin = PIPE和stdout = PIPE。

popen2默認(rèn)關(guān)閉所有文件描述符,但必須使用subprocess.Popen指定close_fds = True。

到此這篇關(guān)于Python中subprocess模塊的用法詳解的文章就介紹到這了,更多相關(guān)Python中subprocess模塊內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論