python調用系統命令popen、system


python調用Shell腳本,有兩種方法:os.system(cmd)或os.popen(cmd),前者返回值是腳本的退出狀態碼,后者的返回值是腳本執行過程中的輸出內容。所以說一般我們認為popen更加強大

os.system(cmd):

該方法在調用完shell腳本后,返回一個16位的二進制 數,低位為殺死所調用腳本的信號號碼,高位為腳本的退出狀態碼,即腳本中“exit 1”的代碼執行后,os.system函數返回值的高位數則是1,如果低位數是0的情況下,則函數的返回值是0×100,換算為10進制得到256。

os.popen(cmd):

這種調用方式是通過管道的方式來實現,函數返回一個file-like的對象,里面的內容是腳本輸出的內容(可簡單理解為echo輸出的內容)。

實例如下:

1 import numpy
2 import os
3 t=os.popen('ls')
4 print t.read()
5 t=os.system('ls')
6 print t

效果:

server.py
setup.py
t
test
test.c
test.nja
test.o
0

-----------------------------------------------------我是分割線---------------------------------------------------------------------------------------------------------

受@趙銳指教,subprocess的Popen更實用。於是趕緊學習了一下

官方指南:https://docs.python.org/2/library/subprocess.html

官方也建議用這個替代(當然unix用戶還有個更新的subprocess32)

 這個模塊粗略的看一下主要是啟用另一個線程,並可獲取輸入,輸出以及錯誤信息等,並提供了subprocess.Popen以及他的幾個封裝函數

先介紹下封裝的函數

一、subprocess.call

  subprocess.call (*popenargs , **kwargs )

執行命令,並等待命令結束,再返回子進程的返回值。參數同Popen。我暫時的理解就是這個是加上了同步的popen。

二、subprocess.check_call

  subprocess.check_call (*popenargs , **kwargs )

執行上面的call命令,並檢查返回值,如果子進程返回非0,則會拋出CalledProcessError異常,這個異常會有個returncode 屬性,記錄子進程的返回值。

三、check_output()

執行程序,並返回其標准輸出.

 

而Popen則用起來更廣泛,用起來和call一樣,只是如果要同步要自己加上wait

借鑒一下屬性

1.Popen.poll():用於檢查子進程是否已經結束。設置並返回returncode屬性。 2.Popen.wait():等待子進程結束。設置並返回returncode屬性。 3.Popen.communicate(input=None):與子進程進行交互。向stdin發送數據,或從stdout和stderr中讀取數據。可選參數input指定發送到子進程的參數。Communicate()返回一個元組:(stdoutdata, stderrdata)。注意:如果希望通過進程的stdin向其發送數據,在創建Popen對象的時候,參數stdin必須被設置為PIPE。同樣,如果希望從stdout和stderr獲取數據,必須將stdout和stderr設置為PIPE。 4.Popen.send_signal(signal):向子進程發送信號。 5.Popen.terminate():停止(stop)子進程。在windows平台下,該方法將調用Windows API TerminateProcess()來結束子進程。 6.Popen.kill():殺死子進程。 7.Popen.stdin:如果在創建Popen對象是,參數stdin被設置為PIPE,Popen.stdin將返回一個文件對象用於策子進程發送指令。否則返回None。 8.Popen.stdout:如果在創建Popen對象是,參數stdout被設置為PIPE,Popen.stdout將返回一個文件對象用於策子進程發送指令。否則返回None。 9.Popen.stderr:如果在創建Popen對象是,參數stdout被設置為PIPE,Popen.stdout將返回一個文件對象用於策子進程發送指令。否則返回None。 10.Popen.pid:獲取子進程的進程ID。 11.Popen.returncode:獲取進程的返回值。如果進程還沒有結束,返回None。 12.subprocess.call(*popenargs, **kwargs):運行命令。該函數將一直等待到子進程運行結束,並返回進程的returncode。文章一開始的例子就演示了call函數。如果子進程不需要進行交互,就可以使用該函數來創建。 13.subprocess.check_call(*popenargs, **kwargs):與subprocess.call(*popenargs, **kwargs)功能一樣,只是如果子進程返回的returncode不為0的話,將觸發CalledProcessError異常。在異常對象中,包括進程的returncode信息。

關於subprocess的安全性:

不像其他的popen函數,不會直接調用/bin/sh來解釋命令,也就是說,命令中的每一個字符都會被安全地傳遞到子進程里。

這里着重介紹一下怎么用這個替換原本的幾個庫

一、替換shell命令

output=`mycmd myarg`
# 替換為
output = check_output(["mycmd", "myarg"]

二、替換shell管道

output=`dmesg | grep hda`
# 替換為
p1 = Popen(["dmesg"], stdout=PIPE)
p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
p1.stdout.close()  # Allow p1 to receive a SIGPIPE if p2 exits.
output = p2.communicate()[0]

三、替換os.system()

status = os.system("mycmd" + " myarg") # 替換為 status = subprocess.call("mycmd" + " myarg", shell=True)

注意:

  • 通常並不需要用shell來調用程序。
  • 用subprocess可以更方便地得到子程序的返回值。

其實,更真實的替換是:

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:])

關於環境變量的例子

os.spawnlpe(os.P_NOWAIT, “/bin/mycmd”, “mycmd”, “myarg”, env)
等效於
Popen(["/bin/mycmd", "myarg"], env={“PATH”: “/usr/bin”})

代替os.popen(), os.popen2(), os.popen3()

pipe = os.popen(“cmd”, ‘r’, bufsize)
等效於
pipe = Popen(“cmd”, shell=True, bufsize=bufsize, stdout=PIPE).stdout

pipe = os.popen(“cmd”, ‘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)

*nix下,os.popen2, os.popen3, os.popen4 也可以接受一個列表做為執行的命令,這時參數會被直接傳給程序,而不經過shell的解釋轉換。如下:

(child_stdin, child_stdout) = os.popen2(["/bin/ls", "-l"], mode, bufsize)
等效於
p = Popen(["/bin/ls", "-l"], bufsize=bufsize, stdin=PIPE, stdout=PIPE)
(child_stdin, child_stdout) = (p.stdin, p.stdout)

返回值處理:

pipe = os.popen(“cmd”, ‘w’)

rc = pipe.close()
if rc != None and rc % 256:
print “There were some errors”
等效於
process = Popen(“cmd”, ‘w’, shell=True, stdin=PIPE)

process.stdin.close()
if process.wait() != 0:
print “There were some errors”

代替popen2模塊里的函數:

(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)

*nix下,popen2 也可以接受一個列表做為執行的命令,這時參數會被直接傳給程序,而不經過shell的解釋轉換。如下:

(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 and popen2.Popen4 基本上也能用 subprocess.Popen 代替,除了以下幾點要注意:

    • 執行失敗的時候Popen會拋出異常
    • capturestderr參數用stderr代替
    • stdin=PIPEstdout=PIPE 必須要指定
    • popen2默認會關掉所有文件描述符,而Popen要指定close_fds=True

 部分內容轉載於http://hi.baidu.com/u_chen/item/fbb839f2fdc6c713a629889e


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM