1. 程式人生 > >Python基礎-subprocess模塊

Python基礎-subprocess模塊

pos taf func spa shell命令 rgs was 解析 除了

我們經常需要通過Python去執行一條系統命令或腳本,系統的shell命令是獨立於你的python進程之外的,每執行一條命令,就是發起一個新進程,通過python調用系統命令或腳本的模塊在python2有os.system,

>>> os.system(‘uname -a‘)
Darwin Alexs-MacBook-Pro.local 15.6.0 Darwin Kernel Version 15.6.0: Sun Jun  4 21:43:07 PDT 2017; root:xnu-3248.70.3~1/RELEASE_X86_64 x86_64
0

這條命令的實現原理是什麽呢?(視頻中講,解釋進程間通信的問題...)

除了os.system可以調用系統命令,,commands,popen2等也可以,比較亂,於是官方推出了subprocess,目地是提供統一的模塊來實現對系統命令或腳本的調用

The subprocess module allows you to spawn new processes, connect to their input/output/error pipes, and obtain their return codes. This module intends to replace several older modules and functions:

  • os.system
  • os.spawn*

The recommended approach to invoking subprocesses is to use the run() function for all use cases it can handle. For more advanced use cases, the underlying Popen interface can be used directly.

The run() function was added in Python 3.5; if you need to retain compatibility with older versions, see the Older high-level API section.

三種執行命令的方法

  • subprocess.run(*popenargs, input=None, timeout=None, check=False, **kwargs) #官方推薦

  • subprocess.call(*popenargs, timeout=None, **kwargs) #跟上面實現的內容差不多,另一種寫法

  • subprocess.Popen() #上面各種方法的底層封裝

run()方法

Run command with arguments and return a CompletedProcess instance.The returned instance will have attributes args, returncode, stdout and stderr. By default, stdout and stderr are not captured, and those attributes will be None. Pass stdout=PIPE and/or stderr=PIPE in order to capture them.

If check is True and the exit code was non-zero, it raises a CalledProcessError. The CalledProcessError object will have the return code in the returncode attribute, and output & stderr attributes if those streams were captured.

If timeout is given, and the process takes too long, a TimeoutExpired exception will be raised.

The other arguments are the same as for the Popen constructor.

標準寫法

subprocess.run([‘df‘,‘-h‘],stderr=subprocess.PIPE,stdout=subprocess.PIPE,check=True)

涉及到管道|的命令需要這樣寫

subprocess.run(‘df -h|grep disk1‘,shell=True) #shell=True的意思是這條命令直接交給系統去執行,不需要python負責解析

call()方法

#執行命令,返回命令執行狀態 , 0 or 非0
>>> retcode = subprocess.call(["ls", "-l"])

#執行命令,如果命令結果為0,就正常返回,否則拋異常
>>> subprocess.check_call(["ls", "-l"])
0

#接收字符串格式命令,返回元組形式,第1個元素是執行狀態,第2個是命令結果 
>>> subprocess.getstatusoutput(‘ls /bin/ls‘)
(0, ‘/bin/ls‘)

#接收字符串格式命令,並返回結果
>>> subprocess.getoutput(‘ls /bin/ls‘)
‘/bin/ls‘

#執行命令,並返回結果,註意是返回結果,不是打印,下例結果返回給res
>>> res=subprocess.check_output([‘ls‘,‘-l‘])
>>> res
b‘total 0\ndrwxr-xr-x 12 alex staff 408 Nov 2 11:05 OldBoyCRM\n‘

Popen()方法

常用參數:

  • args:shell命令,可以是字符串或者序列類型(如:list,元組)
  • stdin, stdout, stderr:分別表示程序的標準輸入、輸出、錯誤句柄
  • preexec_fn:只在Unix平臺下有效,用於指定一個可執行對象(callable object),它將在子進程運行之前被調用
  • shell:同上
  • cwd:用於設置子進程的當前目錄
  • env:用於指定子進程的環境變量。如果env = None,子進程的環境變量將從父進程中繼承。

下面這2條語句執行會有什麽區別?

a=subprocess.run(‘sleep 10‘,shell=True,stdout=subprocess.PIPE)
a=subprocess.Popen(‘sleep 10‘,shell=True,stdout=subprocess.PIPE)

區別是Popen會在發起命令後立刻返回,而不等命令執行結果。這樣的好處是什麽呢?

如果你調用的命令或腳本 需要執行10分鐘,你的主程序不需卡在這裏等10分鐘,可以繼續往下走,幹別的事情,每過一會,通過一個什麽方法來檢測一下命令是否執行完成就好了。

Popen調用後會返回一個對象,可以通過這個對象拿到命令執行結果或狀態等,該對象有以下方法

poll()

Check if child process has terminated. Returns returncode

wait()

Wait for child process to terminate. Returns returncode attribute.

terminate()終止所啟動的進程Terminate the process with SIGTERM

kill() 殺死所啟動的進程 Kill the process with SIGKILL

communicate()與啟動的進程交互,發送數據到stdin,並從stdout接收輸出,然後等待任務結束

>>> a = subprocess.Popen(‘python3 guess_age.py‘,stdout=subprocess.PIPE,stderr=subprocess.PIPE,stdin=subprocess.PIPE,shell=True)

>>> a.communicate(b‘22‘)

(b‘your guess:try bigger\n‘, b‘‘)

send_signal(signal.xxx)發送系統信號

pid 拿到所啟動進程的進程號

Python基礎-subprocess模塊