Subprocess干嘛用的?
subprocess模塊是python從2.4版本開始引入的模塊。主要用來取代 一些舊的模塊方法,如os.system、os.spawn*、os.popen*、commands.*等。subprocess通過子進程來執行外部指令,並通過input/output/error管道,獲取子進程的執行的返回信息。
也就是說subprocess就是OS模塊的升級版。
subprocess模塊中的常用函數
函數 描述 subprocess.run() Python 3.5中新增的函數。執行指定的命令,等待命令執行完成后返回一個包含執行結果的CompletedProcess類的實例。 subprocess.call() 執行指定的命令,返回命令執行狀態,其功能類似於os.system(cmd)。 subprocess.check_call() Python 2.5中新增的函數。 執行指定的命令,如果執行成功則返回狀態碼,否則拋出異常。其功能等價於subprocess.run(..., check=True)。 subprocess.check_output() Python 2.7中新增的的函數。執行指定的命令,如果執行狀態碼為0則返回命令執行結果,否則拋出異常。 subprocess.getoutput(cmd) 接收字符串格式的命令,執行命令並返回執行結果,其功能類似於os.popen(cmd).read()和commands.getoutput(cmd)。 subprocess.getstatusoutput(cmd) 執行cmd命令,返回一個元組(命令執行狀態, 命令執行結果輸出),其功能類似於commands.getstatusoutput()。
1.subprocess.call
父進程等待子進程執行命令,返回子進程執行命令的狀態碼,如果出現錯誤,不進行報錯
第二個參數默認為False,Flase參數為的時候命令需要通過列表的方式傳入,為True的時候可以直接傳入命令。
【在Python的console界面中我們是能夠看到命令結果的,只是獲取不到。想獲取執行的返回結果,請看check_output。】
【不進行報錯解釋:如果我們執行的命令在執行時,操作系統不識別,系統會返回一個錯誤,如:abc命令不存在,這個結果會在console界面中顯示出來,但是我們的Python解釋器不會提示任何信息,如果想讓Python解釋器也進行報錯,請看check_call】
>>> import subprocess >>> obj = subprocess.call(['df','-h'],shell=False) 文件系統 容量 已用 可用 已用% 掛載點 udev 5.8G 0 5.8G 0% /dev tmpfs 1.2G 1.8M 1.2G 1% /run /dev/sda6 393G 137G 237G 37% / tmpfs 5.8G 51M 5.8G 1% /dev/shm tmpfs 5.0M 4.0K 5.0M 1% /run/lock tmpfs 5.8G 0 5.8G 0% /sys/fs/cgroup tmpfs 1.2G 48K 1.2G 1% /run/user/1000 /dev/sda5 412G 26G 386G 7% /media/i3ekr/軟件 /dev/sda1 121G 24G 97G 20% /media/i3ekr/F6AE5B1CAE5AD529 >>> obj = subprocess.call(('df -h'),shell=True) 文件系統 容量 已用 可用 已用% 掛載點 udev 5.8G 0 5.8G 0% /dev tmpfs 1.2G 1.8M 1.2G 1% /run /dev/sda6 393G 137G 237G 37% / tmpfs 5.8G 49M 5.8G 1% /dev/shm tmpfs 5.0M 4.0K 5.0M 1% /run/lock tmpfs 5.8G 0 5.8G 0% /sys/fs/cgroup tmpfs 1.2G 48K 1.2G 1% /run/user/1000 /dev/sda5 412G 26G 386G 7% /media/i3ekr/軟件 /dev/sda1 121G 24G 97G 20% /media/i3ekr/F6AE5B1CAE5AD529
注:shell=True參數會讓subprocess.Popen接受字符串類型的變量作為命令,並調用shell去執行這個字符串.見而言之就是將輸入的參數調用shell去執行,如果不調用那可能就會出現命令找不到的情況.
當shell=False是,subprocess.Popen只接受數組變量作為命令,並將數組的第一個元素作為命令,剩下的全部作為該命令的參數。 默認情況下為false.
2.subprocess.check_call()
用法和call作用一樣,和call的區別是返回值不為0(也就是命令不正確)的時候直接拋出異常。
>>> obj = subprocess.check_call('qwe',shell=False) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/lib/python2.7/subprocess.py", line 181, in check_call retcode = call(*popenargs, **kwargs) File "/usr/lib/python2.7/subprocess.py", line 168, in call return Popen(*popenargs, **kwargs).wait() File "/usr/lib/python2.7/subprocess.py", line 390, in __init__ errread, errwrite) File "/usr/lib/python2.7/subprocess.py", line 1025, in _execute_child raise child_exception OSError: [Errno 2] No such file or directory >>> obj = subprocess.check_call('df',shell=False) 文件系統 1K-塊 已用 可用 已用% 掛載點 udev 6013400 0 6013400 0% /dev tmpfs 1208056 1836 1206220 1% /run /dev/sda6 411798952 143162248 247648800 37% / tmpfs 6040264 48768 5991496 1% /dev/shm tmpfs 5120 4 5116 1% /run/lock tmpfs 6040264 0 6040264 0% /sys/fs/cgroup tmpfs 1208052 48 1208004 1% /run/user/1000 /dev/sda5 431498236 27213864 404284372 7% /media/i3ekr/軟件 /dev/sda1 125830140 24482072 101348068 20% /media/i3ekr/F6AE5B1CAE5AD529
可以用來判斷用戶命令是否出錯可以搭配try來使用。
3.subprocess.Popen()
在一些復雜場景中,我們需要將一個進程的執行輸出作為另一個進程的輸入。在另一些場景中,我們需要先進入到某個輸入環境,然后再執行一系列的指令等。這個時候我們就需要使用到suprocess的Popen()方法。該方法有以下參數:
args:shell命令,可以是字符串,或者序列類型,如list,tuple。
bufsize:緩沖區大小,可不用關心
stdin,stdout,stderr:分別表示程序的標准輸入,標准輸出及標准錯誤
shell:與上面方法中用法相同
cwd:用於設置子進程的當前目錄
env:用於指定子進程的環境變量。如果env=None,則默認從父進程繼承環境變量
universal_newlines:不同系統的的換行符不同,當該參數設定為true時,則表示使用\n作為換行符
4.獲取命令執行后返回的結果:
>>> import subprocess
>>> com = subprocess.Popen('ifconfig',stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
>>> data = com.stdout.read()
>>> data
'enp3s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500\n inet 10.41.8.24 netmask 255.255.252.0 broadcast 10.41.11.255\n inet6 fe80::a993:220a:2a:a488 prefixlen 64 scopeid 0x20<link>\n ether 98:40:bb:20:25:b0 txqueuelen 1000 (Ethernet)\n RX packets 7041415 bytes 6473395772 (6.0 GiB)\n RX errors 0 dropped 0 overruns 0 frame 0\n TX packets 6470453 bytes 3937057528 (3.6 GiB)\n TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0\n\nlo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536\n inet 127.0.0.1 netmask 255.0.0.0\n inet6 ::1 prefixlen 128 scopeid 0x10<host>\n loop txqueuelen 1000 (Local Loopback)\n RX packets 775007 bytes 96639605 (92.1 MiB)\n RX errors 0 dropped 0 overruns 0 frame 0\n TX packets 775007 bytes 96639605 (92.1 MiB)\n TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0\n\nvmnet1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500\n inet 172.16.189.1 netmask 255.255.255.0 broadcast 172.16.189.255\n inet6 fe80::250:56ff:fec0:1 prefixlen 64 scopeid 0x20<link>\n ether 00:50:56:c0:00:01 txqueuelen 1000 (Ethernet)\n RX packets 0 bytes 0 (0.0 B)\n RX errors 0 dropped 0 overruns 0 frame 0\n TX packets 1930 bytes 0 (0.0 B)\n TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0\n\nvmnet8: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500\n inet 172.16.150.1 netmask 255.255.255.0 broadcast 172.16.150.255\n inet6 fe80::250:56ff:fec0:8 prefixlen 64 scopeid 0x20<link>\n ether 00:50:56:c0:00:08 txqueuelen 1000 (Ethernet)\n RX packets 0 bytes 0 (0.0 B)\n RX errors 0 dropped 0 overruns 0 frame 0\n TX packets 1923 bytes 0 (0.0 B)\n TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0\n\nwlp2s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500\n inet 10.42.0.1 netmask 255.255.255.0 broadcast 10.42.0.255\n inet6 fe80::3e8b:4ca8:230f:4f1e prefixlen 64 scopeid 0x20<link>\n ether 70:1c:e7:25:e8:47 txqueuelen 1000 (Ethernet)\n RX packets 394488 bytes 27416908 (26.1 MiB)\n RX errors 0 dropped 3 overruns 0 frame 0\n TX packets 805283 bytes 1207252086 (1.1 GiB)\n TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0\n\n'