国产成人精品久久免费动漫-国产成人精品天堂-国产成人精品区在线观看-国产成人精品日本-a级毛片无码免费真人-a级毛片毛片免费观看久潮喷

您的位置:首頁技術(shù)文章
文章詳情頁

Python實(shí)現(xiàn)subprocess執(zhí)行外部命令

瀏覽:15日期:2022-06-19 17:09:24
目錄一、Python執(zhí)行外部命令1、subprocess模塊簡介2、subprocess模塊的遍歷函數(shù)3、subprocess模塊的Popen類(PyCharm)4、使用python自動安i裝并啟動mongodb一、Python執(zhí)行外部命令1、subprocess模塊簡介

subprocess 模塊允許我們啟動一個(gè)新進(jìn)程,并連接到它們的輸入/輸出/錯誤管道,從而獲取返回值。

這個(gè)模塊用來創(chuàng)建和管理子進(jìn)程。它提供了高層次的接口,用來替換os.system*()、 os.spawn*()、 os.popen*()、os,popen2.*()和commands.*等模塊和函數(shù)。

subprocess提供了一個(gè)名為Popen的類啟動和設(shè)置子進(jìn)程的參數(shù),由于這個(gè)類比較復(fù)雜, subprocess還提供了若干便利的函數(shù),這些函數(shù)都是對Popen類的封裝。

2、subprocess模塊的遍歷函數(shù)

linux安裝ipython

pip3 install ipython

(1)call函數(shù)

call函數(shù)的定義如下:

subprocess.ca11(args, *, stdin=None, stdout=None, stderr=None, she11=False)#運(yùn)行由args參數(shù)提供的命令,等待命令執(zhí)行結(jié)束并返回返回碼。args參數(shù)由字符串形式提供且有多個(gè)命令參數(shù)時(shí),需要提供shell=True參數(shù) args:表示要執(zhí)行的命令。必須是一個(gè)字符串,字符串參數(shù)列表。 stdin、stdout 和 stderr:子進(jìn)程的標(biāo)準(zhǔn)輸入、輸出和錯誤。其值可以是 subprocess.PIPE、subprocess.DEVNULL、一個(gè)已經(jīng)存在的文件描述符、已經(jīng)打開的文件對象或者 None。subprocess.PIPE 表示為子進(jìn)程創(chuàng)建新的管道。subprocess.DEVNULL 表示使用 os.devnull。默認(rèn)使用的是 None,表示什么都不做。另外,stderr 可以合并到 stdout 里一起輸出。 shell:如果該參數(shù)為 True,將通過操作系統(tǒng)的 shell 執(zhí)行指定的命令。

示例代碼:

[root@python ~]# ipython #啟動ipythonPython 3.8.1 (default, Mar 9 2020, 12:35:12) Type ’copyright’, ’credits’ or ’license’ for more informationIPython 7.13.0 -- An enhanced Interactive Python. Type ’?’ for help.In [1]: import subprocess#調(diào)用函數(shù)In [2]: subprocess.call([’ls’,’-l’]) drwxr-xr-x. 2 root root6 10月 31 23:04 公共drwxr-xr-x. 2 root root6 10月 31 23:04 模板drwxr-xr-x. 2 root root6 10月 31 23:04 視頻drwxr-xr-x. 2 root root 4096 10月 31 22:40 圖片drwxr-xr-x. 2 root root6 10月 31 23:04 文檔drwxr-xr-x. 2 root root6 10月 31 23:04 下載drwxr-xr-x. 2 root root6 10月 31 23:04 音樂drwxr-xr-x. 2 root root6 10月 31 15:27 桌面Out[2]: 0In [3]: subprocess.call(’exit 1’,shell=True) Out[3]: 1

(2)check_call函數(shù)

check_call函數(shù)的作用與call函數(shù)類似,區(qū)別在于異常情況下返回的形式不同。

對于call函數(shù),工程師通過捕獲call命令的返回值判斷命令是否執(zhí)行成功,如果成功則返回0,否則的話返回非0,對于check_call函數(shù),如果執(zhí)行成功,返回0,如果執(zhí)行失敗,拋出subrocess.CalledProcessError異常。如下所示:

In [5]: subprocess.check_call([’ls’,’-l’])drwxr-xr-x. 2 root root6 10月 31 23:04 公共drwxr-xr-x. 2 root root6 10月 31 23:04 模板drwxr-xr-x. 2 root root6 10月 31 23:04 視頻drwxr-xr-x. 2 root root 4096 10月 31 22:40 圖片drwxr-xr-x. 2 root root6 10月 31 23:04 文檔drwxr-xr-x. 2 root root6 10月 31 23:04 下載drwxr-xr-x. 2 root root6 10月 31 23:04 音樂drwxr-xr-x. 2 root root6 10月 31 15:27 桌面Out[5]: 0In [6]: subprocess.check_call(’exit 1’,shell=True) -------------------------------------------------------------CalledProcessError Traceback (most recent call last)<ipython-input-6-5e148d3ce640> in <module>----> 1 subprocess.check_call(’exit 1’,shell=True)/usr/local/python381/lib/python3.8/subprocess.py in check_call(*popenargs, **kwargs) 362 if cmd is None: 363 cmd = popenargs[0]--> 364 raise CalledProcessError(retcode, cmd) 365 return 0 366CalledProcessError: Command ’exit 1’ returned non-zero exit status 1.

(3)check_output

Python3中的subprocess.check_output函數(shù)可以執(zhí)行一條sh命令,并返回命令的輸出內(nèi)容,用法如下:

In [10]: output = subprocess.check_output([’df’,’-h’]) In [11]: print(output.decode()) 文件系統(tǒng) 容量 已用 可用 已用% 掛載點(diǎn)/dev/mapper/cl-root 17G 5.2G 12G 31% /devtmpfs 473M 0 473M 0% /devtmpfs489M 92K 489M 1% /dev/shmtmpfs489M 7.1M 482M 2% /runtmpfs489M 0 489M 0% /sys/fs/cgroup/dev/sda1 1014M 173M 842M 18% /boottmpfs 98M 16K 98M 1% /run/user/42tmpfs 98M 0 98M 0% /run/user/0In [12]: lines = output.decode().split(’n’)In [13]: lines Out[13]: [’文件系統(tǒng) 容量 已用 可用 已用% 掛載點(diǎn)’, ’/dev/mapper/cl-root 17G 5.2G 12G 31% /’, ’devtmpfs 473M 0 473M 0% /dev’, ’tmpfs489M 92K 489M 1% /dev/shm’, ’tmpfs489M 7.1M 482M 2% /run’, ’tmpfs489M 0 489M 0% /sys/fs/cgroup’, ’/dev/sda1 1014M 173M 842M 18% /boot’, ’tmpfs 98M 16K 98M 1% /run/user/42’, ’tmpfs 98M 0 98M 0% /run/user/0’, ’’]In [14]: for line in lines[1:-1]: ...: if line: ...: print(line.split()[-2]) ...: #截取掛載點(diǎn)數(shù)據(jù)31%0%1%2%0%18%1%0%

在子進(jìn)程執(zhí)行命令,以字符串形式返回執(zhí)行結(jié)果的輸出。如果子進(jìn)程退出碼不是0,拋出subprocess.CalledProcessError異常,異常的output字段包含錯誤輸出:

In [19]: try: ...: output = subprocess.check_output([’df’,’-h’]).decode() #正確的 ...: except subprocess.CalledProcessError as e: ...: output = e.output ...: code = e.returncode //正確的沒有任何輸出

In [23]: try: ...: output = subprocess.check_output([’wsd’,’-h’], stderr=subprocess.STDOUT) ...: .decode() #錯誤的 ...: except subprocess.CalledProcessError as e: ...: output = e.output ...: code = e.returncode ...:

//前面的錯誤代碼省略FileNotFoundError: [Errno 2] No such file or directory: ’wsd’

3、subprocess模塊的Popen類(PyCharm)

實(shí)際上,我們上面的三個(gè)函數(shù)都是基于Popen()的封裝(wrapper)。這些封裝的目的在于讓我們?nèi)菀资褂米舆M(jìn)程。當(dāng)我們想要更個(gè)性化我們的需求的時(shí)候,就要轉(zhuǎn)向Popen類,該類生成的對象用來代表子進(jìn)程。

subprocess模塊中基本的進(jìn)程創(chuàng)建和管理由Popen類來處理 subprocess.popen是用來替代os.popen的 Popen 是 subprocess的核心,子進(jìn)程的創(chuàng)建和管理都靠它處理。

構(gòu)造函數(shù):

class subprocess.Popen(args, bufsize=-1, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=True, shell=False, cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0,restore_signals=True, start_new_session=False, pass_fds=(),*, encoding=None, errors=None)

(1)常用參數(shù):args:shell命令,可以是字符串或者序列類型(如:list,元組)bufsize:緩沖區(qū)大小。當(dāng)創(chuàng)建標(biāo)準(zhǔn)流的管道對象時(shí)使用,默認(rèn)-1。

0:不使用緩沖區(qū) 1:表示行緩沖,僅當(dāng)universal_newlines=True時(shí)可用,也就是文本模式 正數(shù):表示緩沖區(qū)大小 負(fù)數(shù):表示使用系統(tǒng)默認(rèn)的緩沖區(qū)大小。

stdin, stdout, stderr:分別表示程序的標(biāo)準(zhǔn)輸入、輸出、錯誤句柄preexec_fn:只在 Unix 平臺下有效,用于指定一個(gè)可執(zhí)行對象(callable object),它將在子進(jìn)程運(yùn)行之前被調(diào)用shell:如果該參數(shù)為 True,將通過操作系統(tǒng)的 shell 執(zhí)行指定的命令。cwd:用于設(shè)置子進(jìn)程的當(dāng)前目錄。env:用于指定子進(jìn)程的環(huán)境變量。如果 env = None,子進(jìn)程的環(huán)境變量將從父進(jìn)程中繼承。

創(chuàng)建一個(gè)子進(jìn)程,然后執(zhí)行一個(gè)簡單的命令:

>>> import subprocess>>> p = subprocess.Popen(’ls -l’, shell=True)>>> total 164-rw-r--r-- 1 root root 133 Jul 4 16:25 admin-openrc.sh-rw-r--r-- 1 root root 268 Jul 10 15:55 admin-openrc-v3.sh...>>> p.returncode>>> p.wait()0>>> p.returncode0

這里也可以使用 p = subprocess.Popen([’ls’, ’-cl’]) 來創(chuàng)建子進(jìn)程。

(2)Popen 對象的屬性

<1> p.pid:子進(jìn)程的PID。

<2> p.returncode:該屬性表示子進(jìn)程的返回狀態(tài),returncode可能有多重情況:

None —— 子進(jìn)程尚未結(jié)束; ==0 —— 子進(jìn)程正常退出; > 0—— 子進(jìn)程異常退出,returncode對應(yīng)于出錯碼; < 0—— 子進(jìn)程被信號殺掉了。

<3> p.stdin, p.stdout, p.stderr:子進(jìn)程對應(yīng)的一些初始文件,如果調(diào)用Popen()的時(shí)候?qū)?yīng)的參數(shù)是subprocess.PIPE,則這里對應(yīng)的屬性是一個(gè)包裹了這個(gè)管道的 file 對象。

(3)Popen 對象方法

poll(): 檢查進(jìn)程是否終止,如果終止返回 returncode,否則返回 None。 wait(timeout): 等待子進(jìn)程終止。 communicate(input,timeout): 和子進(jìn)程交互,發(fā)送和讀取數(shù)據(jù)。 send_signal(singnal): 發(fā)送信號到子進(jìn)程 。 terminate(): 停止子進(jìn)程,也就是發(fā)送SIGTERM信號到子進(jìn)程。 kill(): 殺死子進(jìn)程。發(fā)送 SIGKILL 信號到子進(jìn)程。

子進(jìn)程的PID存儲在child.pid

import timeimport subprocessdef cmd(command): subp = subprocess.Popen(command,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE,encoding='utf-8') subp.wait(2) if subp.poll() == 0:print(subp.communicate()[1]) else:print('失敗')cmd('java -version')cmd('exit 1')

輸出結(jié)果如下:

java version '1.8.0_31'Java(TM) SE Runtime Environment (build 1.8.0_31-b13)Java HotSpot(TM) 64-Bit Server VM (build 25.31-b07, mixed mode)

失敗

(4)子進(jìn)程的文本流控制(沿用child子進(jìn)程) 子進(jìn)程的標(biāo)準(zhǔn)輸入,標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯誤也可以通過如下屬性表示:

child.stdin child.stdout child.stderr

我們可以在Popen()建立子進(jìn)程的時(shí)候改變標(biāo)準(zhǔn)輸入、標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯誤,并可以利用subprocess.PIPE將多個(gè)子進(jìn)程的輸入和輸出連接在一起,構(gòu)成管道(pipe):

import subprocesschild1 = subprocess.Popen(['ls','-l'], stdout=subprocess.PIPE)child2 = subprocess.Popen(['wc'], stdin=child1.stdout,stdout=subprocess.PIPE)out = child2.communicate()print(out)

執(zhí)行結(jié)果如下:

(b’ 2 11 60n’, None)

subprocess.PIPE實(shí)際上為文本流提供一個(gè)緩存區(qū)。child1的stdout將文本輸出到緩存區(qū),隨后child2的stdin從該P(yáng)IPE中將文本讀取走。child2的輸出文本也被存放在PIPE中,直到communicate()方法從PIPE中讀取出PIPE中的文本。

要注意的是,communicate()是Popen對象的一個(gè)方法,該方法會阻塞父進(jìn)程,直到子進(jìn)程完成。

我們還可以利用communicate()方法來使用PIPE給子進(jìn)程輸入:

import subprocesschild = subprocess.Popen(['cat'], stdin=subprocess.PIPE)child.communicate('vamei'.encode())

我們啟動子進(jìn)程之后,cat會等待輸入,直到我們用communicate()輸入'vamei'。

通過使用subprocess包,我們可以運(yùn)行外部程序。這極大的拓展了Python的功能。如果你已經(jīng)了解了操作系統(tǒng)的某些應(yīng)用,你可以從Python中直接調(diào)用該應(yīng)用(而不是完全依賴Python),并將應(yīng)用的結(jié)果輸出給Python,并讓Python繼續(xù)處理。shell的功能(比如利用文本流連接各個(gè)應(yīng)用),就可以在Python中實(shí)現(xiàn)。

4、使用python自動安i裝并啟動mongodb

PyCharm記得連接linux

簡易流程

Python自動化運(yùn)維 --> 基于shell命令進(jìn)行封裝 編寫自動化腳本 --> 用Python語法封裝shell命令的執(zhí)行過程 python執(zhí)行shell命令 --> python外部命令 python函數(shù)執(zhí)行shell命令 os.system(cmd):執(zhí)行cmd指令 subprocess模塊

subprocess.call([’ls’,’-l’])subprocess.call(’ll’ , shell=True)

運(yùn)行成功: 返回0運(yùn)行失敗: 返回非0

subprocess. check_call ([’ls’, ’-l’])subprocess. check_call (’ll’, shell=True)

運(yùn)行成功: 返回0運(yùn)行失敗: 返回CalledProcessError

subprocess. check_ output([’cat’, ’apache.log’], stderr= subprocess.STDOUT)

運(yùn)行成功:返回命令的輸出結(jié)果運(yùn)行失敗:自定義錯誤輸出stderr

subprocess模塊的Popen類

(1)PyCharm創(chuàng)建文件

# coding=utf-8import subprocessimport osimport shutilimport tarfile# 執(zhí)行外部命令的函數(shù)def execute_cmd(cmd): ’’’執(zhí)行shell命令’’’ p = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = p.communicate() if p.returncode != 0:return p.returncode, stderr return p.returncode, stdout# 解壓def unpackage_mongo(package, package_dir): # 獲取MongoDB壓縮包的主文件名,也就是解壓后的目錄名稱 # mongodb-linux-x86_64-rhe170-4.2.3 unpackage_dir = os.path.splitext(package)[0] if os.path.exists(unpackage_dir):shutil.rmtree(unpackage_dir) if os.path.exists(package_dir):shutil.rmtree(package_dir) # 解壓 try:t = tarfile.open(package, ’r:gz’)t.extractall(’.’)print(’tar is ok.’) except Exception as e:print(e) # 重命名 shutil.move(unpackage_dir, ’mongo’)# 創(chuàng)建mongodatadef create_datadir(data_dir): if os.path.exists(data_dir):shutil.rmtree(data_dir) os.mkdir(data_dir)# 拼接啟動MongoDBdef format_mongod_commamd(package_dir, data_dir, logfile): # mongo/bin/mongod mongod = os.path.join(package_dir, ’bin’, ’mongod’) # mongo/bin/mongod --fork --logpath mongodata/mongod.log --dbpath mongodata mongod_format = '''{0} --fork --dbpath {1} --logpath {2}''' return mongod_format.format(mongod, data_dir, logfile)# 啟動MongoDBdef start_mongod(cmd): returncode, out = execute_cmd(cmd) if returncode != 0:raise SystemExit(’execute {0} error:{1}’.format(cmd, out)) else:print(’execute {0} successfuly.’.format(cmd))#入口函數(shù)def main(): package = ’mongodb-linux-x86_64-rhel70-4.2.3.tgz’ cur_dir = os.path.abspath(’.’) package_dir = os.path.join(cur_dir, ’mongo’) data_dir = os.path.join(cur_dir, ’mongodata’) logfile = os.path.join(data_dir, ’mongod.log’) # 判斷MongoDB壓縮包是否存在 if not os.path.exists(package):raise SystemExit(’{0} not found.’.format(package)) # 解壓 unpackage_mongo(package, package_dir) create_datadir(data_dir) # 啟動mongodb start_mongod(format_mongod_commamd(package_dir, data_dir, logfile)) # 配置環(huán)境變量 os.system(’echo 'export PATH=./mongo/bin:$PATH' > ~/.bash_profile’) os.system(’source ~/.bash_profile’) os.system(’./mongo/bin/mongo’)main() 在這段程序中,我們首先在main函數(shù)中定義了幾個(gè)變量,包括當(dāng)前目錄的路徑、MongoDB二進(jìn)制文件所在的路徑、MongoDB數(shù)據(jù)目錄所在的路徑,以及MongoDB的日志文件。 隨后,我們判斷MongoDB的安裝包是否存在,如果不存在,則通過拋出SystemExit異常的方式結(jié)束程序。 在unpackage_mongo函數(shù)中,我們通過Python程序得到MongoDB安裝包解壓以后的目錄。如果目錄已經(jīng)存在,則刪除該目錄。隨后,我們使用tarfile解MongoDB數(shù)據(jù)庫,解壓完成后,將命令重命名為mongo目錄。 在create_datadir目錄中,我們首先判斷MongoDB數(shù)據(jù)庫目錄是否存在,如果存在,則刪除該目錄,隨后再創(chuàng)建MongoDB數(shù)據(jù)庫目錄。 在start_mongod函數(shù)中, 我們執(zhí)行MongoDB數(shù)據(jù)庫的啟動命令啟動MongoDB數(shù)據(jù)庫。為了在Python代碼中執(zhí)行shell命令,我們使用了subprocess庫。 我們將subprocess庫執(zhí)行she11命令的邏輯封裝成execute_cmd函數(shù),在執(zhí)行shell命令時(shí),直接調(diào)用該函數(shù)即可。

(2)將PyCharm中的文件上傳到Linux

如果,是直接調(diào)用Linux中文件可用:

Python實(shí)現(xiàn)subprocess執(zhí)行外部命令

如果是本地創(chuàng)建:

Python實(shí)現(xiàn)subprocess執(zhí)行外部命令

(3)Linux執(zhí)行腳本,并測試記得進(jìn)入PyCharm與linux連接的目錄(目前是/opt)

[root@python opt]# python auto_install_mongodb.py #執(zhí)行提前編寫好的腳本tar is ok.execute /opt/mongo/bin/mongod --fork --dbpath /opt/mongodata --logpath /opt/mongodata/mongod.log successfuly.[root@python opt]# netstat -anpt | grep mongo #查看mongo是否啟動tcp0 0 127.0.0.1:27017 0.0.0.0:* LISTEN 4616mongod [root@python opt]# ls #查看是否生成mongo目錄01find_cmd.py bb.bmp mongodb-linux-x86_64-rhel70-4.2.3.tgzaaa.jpg cc.png rhadc.txt mongo subprocess_demoauto_install_mongodb.py mongodata[root@python opt]# cd mongo[root@python mongo]# cd bin/[root@python bin]# ./mongo #進(jìn)入mongoMongoDB shell version v4.2.3connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodbImplicit session: session { 'id' : UUID('c302ff50-7e27-40b7-8046-8441af8cb965') }MongoDB server version: 4.2.3> show databases; #查看數(shù)據(jù)庫admin 0.000GBconfig 0.000GBlocal 0.000GB

到此這篇關(guān)于Python實(shí)現(xiàn)subprocess執(zhí)行外部命令的文章就介紹到這了,更多相關(guān)Python 執(zhí)行外部命令內(nèi)容請搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

標(biāo)簽: Python 編程
相關(guān)文章:
主站蜘蛛池模板: 久久这里只有精品免费视频 | 国产网站在线 | 国产亚洲高清视频 | 91成人网| 美女一级毛片免费看看 | 欧美a欧美 | 国产精品自在线天天看片 | 全免费a级毛片免费毛视频 全午夜免费一级毛片 | 成人毛片在线播放 | 91亚洲精品国产第一区 | 免费国产一级 | 亚洲国产精品久久久久 | 欧美一级级a在线观看 | 国产欧美精品综合一区 | 午夜香蕉成视频人网站高清版 | 日韩精品无码一区二区三区 | 99久久精品免费观看区一 | 国产精品久久久久久久久久久久久久 | 一级毛片免费播放 | 日本美女黄色一级片 | 久久久久久免费观看 | 99精品视频在线播放2 | 日本红怡院亚洲红怡院最新 | 91精品国产高清久久久久 | chinese性老妇中国 | 国产精品一区二区资源 | 97超视频在线观看 | 国产区网址 | 午夜一区二区福利视频在线 | 日韩亚洲精品不卡在线 | 91理论片午午伦夜理片久久 | 三级黄色在线观看 | 久久久久久久久中文字幕 | 午夜爽爽性刺激一区二区视频 | 2021国产精品自在拍在线播放 | 久久久国产一区二区三区 | 精品国产三级在线观看 | 国产成人综合91精品 | 免费观看成人www精品视频在线 | 岛国午夜精品视频在线观看 | www.91久久|