企业🤖AI Agent构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
[TOC] * * * * * > * 模块的分类 > 1. python内置模块(标准库) > 2. 开源模块 > 3. 自定义模块 > ## 1. shelve模块 在python3中我们使用json或者pickle持久化数据,能dump多次,但只能load一次,因为先前的数据已经被后面dump的数据覆盖掉了。如果我们想要实现dump和load多次,可以使用shelve模块。shelve模块可以持久化所有pickle所支持的数据类型。类似于键值对的文件序列化 1. 写入数据(打开文件,写入键值,关闭文件) ~~~ import shelve import datetime d = shelve.open('shave.txt') info = {"age":25,"name":'dailin'} name = ['alex','rain','peter'] d['info'] = info d['name'] = name date = datetime.datetime.now() d['date'] = date d.close() ~~~ 2. 读数据(打开文件,获取键对应的值,关闭文件) ~~~ import shelve d = shelve.open('shave.txt') print(d.get('info')) d.close() ~~~ ## 2. os * 文件与路径的操作 在自动化测试中,经常需要查找操作文件,比如说查找配置文件(从而读取配置文件的信息),查找测试报告(从而发送测试报告邮件),经常要对大量文件和大量路径进行操作,这就依赖于os模块,所以今天整理下比较常用的几个方法。网上这方面资料也很多,每次整理,只是对自己所学的知识进行梳理,从而加深对某个模块的使用。 #### 2.1 当前路径及路径下的文件 * os.getcwd(): 查看当前所在路径。 * os.listdir(path): 列举目录下的所有文件。返回的是列表类型。 ~~~ >>> import os >>> os.getcwd() 'D:\\pythontest\\ostest' >>> os.listdir(os.getcwd()) ['hello.py', 'test.txt'] ~~~ #### 2.2 绝对路径 * os.path.abspath(path):返回path的绝对路径。 ~~~ # 获取当前绝对路径 . >>> os.path.abspath('.') 'D:\\pythontest\\ostest' # 获取当前路径上一级绝对路径 .. >>> os.path.abspath('..') 'D:\\pythontest' ~~~ #### 2.3 查看路径的文件夹部分和文件名部分 * os.path.split(path): 将路径分解为(文件夹,文件名),返回的是元组类型。可以看出,若路径字符串最后一个字符是\,则只有文件夹部分有值;若路径字符串中均无\,则只有文件名部分有值。若路径字符串有\,且不在最后,则文件夹和文件名均有值。且返回的文件夹的结果不包含\. * os.path.join(path1,path2,...):将path进行组合,若其中有绝对路径,则之前的path将被删除。 ~~~ # 切分路径与文件 >>> os.path.split('D:\\pythontest\\ostest\\Hello.py') ('D:\\pythontest\\ostest', 'Hello.py') >>> os.path.split('.') ('', '.') >>> os.path.split('D:\\pythontest\\ostest\\') ('D:\\pythontest\\ostest', '') >>> os.path.split('D:\\pythontest\\ostest') ('D:\\pythontest', 'ostest') >>> os.path.join('D:\\pythontest', 'ostest') 'D:\\pythontest\\ostest' # 路径与文件拼接 >>> os.path.join('D:\\pythontest\\ostest', 'hello.py') 'D:\\pythontest\\ostest\\hello.py' # 绝对路径与绝对路径拼接,前边的被覆盖 >>> os.path.join('D:\\pythontest\\b', 'D:\\pythontest\\a') 'D:\\pythontest\\a' ~~~ * os.path.dirname(path):返回path中的文件夹部分,结果不包含'\' ~~~ >>> os.path.dirname('D:\\pythontest\\ostest\\hello.py') 'D:\\pythontest\\ostest' >>> os.path.dirname('.') '' >>> os.path.dirname('D:\\pythontest\\ostest\\') 'D:\\pythontest\\ostest' >>> os.path.dirname('D:\\pythontest\\ostest') 'D:\\pythontest' ~~~ * os.path.basename(path):返回path中的文件名。 ~~~ >>> os.path.basename('D:\\pythontest\\ostest\\hello.py') 'hello.py' >>> os.path.basename('.') '.' >>> os.path.basename('D:\\pythontest\\ostest\\') '' >>> os.path.basename('D:\\pythontest\\ostest') 'ostest' ~~~ #### 2.4 查看文件时间 * os.path.getmtime(path): 文件或文件夹的最后修改时间,从新纪元到访问时的秒数。 * os.path.getatime(path): 文件或文件夹的最后访问时间,从新纪元到访问时的秒数。 * os.path.getctime(path): 文件或文件夹的创建时间,从新纪元到访问时的秒数。 ~~~ >>> os.path.getmtime('D:\\pythontest\\ostest\\hello.py') 1481695651.857048 >>> os.path.getatime('D:\\pythontest\\ostest\\hello.py') 1481687717.8506615 >>> os.path.getctime('D:\\pythontest\\ostest\\hello.py') 1481687717.8506615 ~~~ #### 2.5 查看文件大小 * os.path.getsize(path): 文件或文件夹的大小,若是文件夹返回0。 ~~~ >>> os.path.getsize('D:\\pythontest\\ostest\\hello.py') 58L >>> os.path.getsize('D:\\pythontest\\ostest') 0L ~~~ #### 2.6 查看文件是否存在 * os.path.exists(path): 文件或文件夹是否存在,返回True 或 False。 ~~~ >>> os.listdir(os.getcwd()) ['hello.py', 'test.txt'] >>> os.path.exists('D:\\pythontest\\ostest\\hello.py') True >>> os.path.exists('D:\\pythontest\\ostest\\Hello.py') True >>> os.path.exists('D:\\pythontest\\ostest\\Hello1.py') False ~~~ #### 2.7 一些表现形式参数 os中定义了一组文件、路径在不同操作系统中的表现形式参数,如: ~~~ >>> os.sep # 系统路径分隔符 '\\' >>> os.extsep '.' >>> os.pathsep # 输出用于分割文件路径的字符串 ';' >>> os.linesep # 获取系统换行符 '\r\n' ~~~ #### 2.8 实例说明 在自动化测试过程中,常常需要发送邮件,将最新的测试报告文档发送给相关人员查看,这是就需要查找最新文件的功能。 举例:查找文件夹下最新的文件。 ~~~ import os def new_file(test_dir): #列举test_dir目录下的所有文件(名),结果以列表形式返回。 lists=os.listdir(test_dir) #sort按key的关键字进行升序排序,lambda的入参fn为lists列表的元素,获取文件的最后修改时间,所以最终以文件时间从小到大排序 #最后对lists元素,按文件修改时间大小从小到大排序。 lists.sort(key=lambda fn:os.path.getmtime(test_dir+'\\'+fn)) #获取最新文件的绝对路径,列表中最后一个值,文件夹+文件名 file_path=os.path.join(test_dir,lists[-1]) return file_path #返回D:\pythontest\ostest下面最新的文件 print new_file('D:\\system files\\workspace\\selenium\\email126pro\\email126\\report') ~~~ ~~~ # 关于lambda的用法(python中单行的最小函数): key=lambda fn:os.path.getmtime(test_dir+'\\'+fn) #相当于 def key(fn): return os.path.getmtime(test_dir+'\\'+fn) ~~~ #### 2.9 遍历文件 os.walk(top, topdown=True, onerror=None, followlinks=False) 可以得到许多个三元tupple(dirpath, dirnames, filenames), 即每个文件夹的(文件夹,文件夹所有子文件夹列表,文件夹下的所有文件列表) dirpath 是一个string,代表目录的路径, dirnames 是一个list,包含了dirpath下所有子目录的名字。 filenames 是一个list,包含了非目录文件的名字。 这些名字不包含路径信息,如果需要得到全路径,需要使用os.path.join(dirpath, name). 循环遍历work目录下的文件 ~~~ for dirpath, dirnames, filenames in os.walk('C:\\Users\\Administrator\\Desktop\\work'): for file in filenames: fullpath = os.path.join(dirpath, file) print(fullpath) ~~~ ~~~ # 根目录 # 根目录下的子目录 # 根目录下的文件 ('C:\\Users\\Administrator\\Desktop\\work', ['fastdfsClient', 'PythonRedis'], ['daily.txt', 'daily.txt.bak', 'fastdfsClient.rar', ('C:\\Users\\Administrator\\Desktop\\work\\fastdfsClient', ['.idea', '.settings', 'bin', 'lib', 'src'], ['.classpath', '.project', 'fastdfsClient.iml']) ('C:\\Users\\Administrator\\Desktop\\work\\fastdfsClient\\.idea', ['libraries'], ['misc.xml', 'modules.xml', 'workspace.xml']) ('C:\\Users\\Administrator\\Desktop\\work\\fastdfsClient\\.idea\\libraries', [], ['jdk1_8.xml']) ('C:\\Users\\Administrator\\Desktop\\work\\fastdfsClient\\.settings', [], ['org.eclipse.jdt.core.prefs']) ('C:\\Users\\Administrator\\Desktop\\work\\fastdfsClient\\bin', ['cn'], []) ('C:\\Users\\Administrator\\Desktop\\work\\fastdfsClient\\bin\\cn', ['itcast'], []) ('C:\\Users\\Administrator\\Desktop\\work\\fastdfsClient\\bin\\cn\\itcast', ['fastdfs'], []) ('C:\\Users\\Administrator\\Desktop\\work\\fastdfsClient\\bin\\cn\\itcast\\fastdfs', ['cliennt'], []) ('C:\\Users\\Administrator\\Desktop\\work\\fastdfsClient\\bin\\cn\\itcast\\fastdfs\\cliennt', [], ['FastdfsClientTest.class', 'fdfs_client.conf']) ('C:\\Users\\Administrator\\Desktop\\work\\fastdfsClient\\lib', [], ['fastdfs_client_v1.20.jar', 'junit-4.9.jar', 'lib.lnk']) ('C:\\Users\\Administrator\\Desktop\\work\\fastdfsClient\\src', ['cn'], []) ('C:\\Users\\Administrator\\Desktop\\work\\fastdfsClient\\src\\cn', ['itcast'], []) ('C:\\Users\\Administrator\\Desktop\\work\\fastdfsClient\\src\\cn\\itcast', ['fastdfs'], []) ('C:\\Users\\Administrator\\Desktop\\work\\fastdfsClient\\src\\cn\\itcast\\fastdfs', ['cliennt'], []) ('C:\\Users\\Administrator\\Desktop\\work\\fastdfsClient\\src\\cn\\itcast\\fastdfs\\cliennt', [], ['FastdfsClientTest.java', 'fdfs_client.conf']) ('C:\\Users\\Administrator\\Desktop\\work\\PythonRedis', ['.idea', '__pycache__'], ['client.conf', 'config$py.class', 'config.py', 'PythonFdfsRedis.py', 'test.py']) ('C:\\Users\\Administrator\\Desktop\\work\\PythonRedis\\.idea', ['inspectionProfiles'], ['misc.xml', 'modules.xml', 'PythonRedis.iml', 'workspace.xml']) ('C:\\Users\\Administrator\\Desktop\\work\\PythonRedis\\.idea\\inspectionProfiles', [], []) ('C:\\Users\\Administrator\\Desktop\\work\\PythonRedis\\__pycache__', [], ['config.cpython-36.pyc']) ~~~ ### 2.10 os.environ 用户获取系统信息 ~~~ os.environ.keys() 主目录下所有的key os.environ['HOMEPATH']:当前用户主目录。 ~~~ ## 3. sys sys模块提供了一系列有关Python运行环境的变量和函数。 * sys.argv 可以用sys.argv获取当前正在执行的命令行参数的参数列表(list)。 ~~~ 变量 解释 sys.argv[0] 当前程序名 sys.argv[1] 第一个参数 sys.argv[0] 第二个参数 ~~~ ~~~ # encoding: utf-8 # filename: argv_test.py import sys # 获取脚本名字 print 'The name of this program is: %s' %(sys.argv[0]) # 获取参数列表 print 'The command line arguments are:' for i in sys.argv: print i # 统计参数个数 print 'There are %s arguments.'%(len(sys.argv)-1) ~~~ * sys.platform 获取当前执行环境的平台,如win32表示是Windows 32bit操作系统,linux2表示是linux平台; * sys.path path是一个目录列表,供Python从中查找第三方扩展模块。在python启动时,sys.path根据内建规则、PYTHONPATH变量进 ## 4. xml ~~~ <data> <country name="Liechtenstein"> <rank updated="yes">2</rank> <year updated_by="Alex" updated_by_tuna="yes">2010</year> <gdppc>141100</gdppc> <neighbor direction="E" name="Austria" /> <neighbor direction="W" name="Switzerland" /> </country> <country name="Singapore"> <rank updated="yes">5</rank> <year updated_by="Alex" updated_by_tuna="yes">2013</year> <gdppc>59900</gdppc> <neighbor direction="N" name="Malaysia" /> </country> <country name="Panama"> <rank updated="yes">69</rank> <year updated_by="Alex" updated_by_tuna="yes">2013</year> <gdppc>13600</gdppc> <neighbor direction="W" name="Costa Rica" /> <neighbor direction="E" name="Colombia" /> <info> <population>8</population> <size>960</size> </info> </country> </data> ~~~ #### 4.1 查找 ~~~ import xml.etree.ElementTree as etree # 解析树 parsedTree = etree.parse('xmltest.xml') root = parsedTree.getroot() for child in root: print(child.tag,child.attrib) for node in child: print(node.tag,node.text) # 获取year标签的迭代器 for node in root.iter('year'): print(node.tag, node.text) ~~~ #### 4.2 修改 ~~~ __author__ = 'dailin' import xml.etree.ElementTree as etree tree = etree.parse('xmltest.xml') root = tree.getroot() # 获取year标签的迭代器 for node in root.iter('year'): new_year = int(node.text)+1 node.text = str(new_year) node.set('updated_by_tuna','yes') # 加属性 tree.write('xmltest.xml') # 写回去 # 删除 for country in root.findall('country'): rank = int(country.find('rank').text) if rank > 50: root.remove(country) tree.write('output.xml') ~~~ #### 4.3 创建 ~~~ __author__ = 'dailin' import xml.etree.ElementTree as etree new_xml = etree.Element("personinfolist") # 根节点 # 给new_xml 添加子节点personinfo personinfo = etree.SubElement(new_xml, "personinfo", attrib={"enrolled": "yes"}) # 给personinfo节点添加子节点name name = etree.SubElement(personinfo, "name") name.text = "Alex Li" # name节点文本 age = etree.SubElement(personinfo, "age", attrib={"checked": "no"}) age.text = '56' sex = etree.SubElement(personinfo, "sex") sex.text='women' personinfo2 = etree.SubElement(new_xml, "personinfo", attrib={"enrolled": "no"}) name = etree.SubElement(personinfo2, "name") name.text = "Oldboy Ran" age = etree.SubElement(personinfo2, "age") age.text = '19' et = etree.ElementTree(new_xml) # 生成文档对象xml_declaration=True xml声明 et.write("createdByTuna.xml", encoding="utf-8", xml_declaration=True) ~~~ 得到 ~~~ <?xml version='1.0' encoding='utf-8'?> <personinfolist> <personinfo enrolled="yes"> <name>Alex Li</name> <age checked="no">56</age> <sex>women</sex> </personinfo> <personinfo enrolled="no"> <name>Oldboy Ran</name> <age>19</age> </personinfo> </personinfolist> ~~~ ## 5. ConfigParser 一,首先说说 所谓 ini 文件以及 ini的文件格式: ini 文件其实就是所谓的初始化配置文件,一般的格式为: ~~~ [SECTION0] # 相当于一个配置分类 key0 = value0 # 配置项 key1 = value1 [SECTION1] key0 = value0 key1 = value1 ~~~ * 如 ~~~ [config] --oltp-tables-count=10 --oltp-table-size=100000 --num-threads=8 --max-time=600 ~~~ 二,configparser包 > ConfigParser包是创建一个管理对象,再把配置文件read进去,做了其他操作后,再以打开方式打开文件,写回文件里。(注意!是以打开方式!打开方式!不是追加方式!) > 因为它本身的机制就是会先把文件复制一份,进行操作后,再整个文件内容写回文件里的。 > 三,相关操作:(一个 item 由 KEY和VALUE组成) > cfg = configparser.ConfigParser() > 创建一个管理对象 cfg > cfg.read(file_path) > 把一个 ini文件读到cfg中 > se_list = cfg.sections() > #用一个list存放ini文件中的所有 SECTIONS > item = cfg.items(SECTION) > #用一个列表item存放一个SECTION中的所有items(KEY--VALUE) > cfg.remove_option(se,key) > #删除一个SECTION中的一个item(以键值KEY为标识) > cfg.remove_section(se) > #删除一个SECTION > cfg.add_section(se) > #增加一个SECTION > cfg.set(se,key,value) > #往一个SECTION中增加一个 item(KEY--VALUE) > cfg.wrtie(fp) > #往文件描述符指向的文件中写入修改后的内容 # -*- codeding: utf-8 -*- import sys import os import configparser #导入 configparser包 class client_info(object): def __init__(self,file): self.file = file self.cfg = configparser.ConfigParser() #创建一个管理对象。 def cfg_load(self): self.cfg.read(self.file) #把文件导入管理对象中,把文件内容load到内存中 def cfg_dump(self): se_list = self.cfg.sections() #cfg.sections()显示文件中的所有 section print('==================>') for se in se_list: print(se) print(self.cfg.items(se)) print('==================>') def delete_item(self,se,key): self.cfg.remove_option(se,key) #在section中删除一个item def delete_section(self,se): self.cfg.remove_section(se) #删除一个section def add_section(self,se): self.cfg.add_section(se) #添加一个section def set_item(self,se,key,value): self.cfg.set(se,key,value) #往section中添加一个item(一个item由key和value构成) def save(self): fd = open(self.file,'w') self.cfg.write(fd) #在内存中修改的内容写回文件中,相当于保存 fd.close() if __name__== '__main__': info = client_info('client.ini') info.cfg_load() info.add_section('ZJE') info.set_item('ZJE','name','zhujunwen') info.cfg_dump() info.save() ~~~ import configparser config = configparser.ConfigParser() config.read("ConfigParser.ini") # 获取配置下的配置值,[config] 代表一个section tableCount = config.get('config','--oltp-tables-count') tableSize = config.get('config','--oltp-table-size') threadNum = config.get('config','--num-threads') maxTime = config.get('config','--max-time') # 获取配置下的选项 print("table count:" + tableCount) print("table size:" + tableSize) print("thred num:" + threadNum) print("max time:" + maxTime) mysql = config.options("config") print("option:" , mysql) # 获取section下的所有配置项 item = config.items("config") print("item:",item) ~~~ * 配置文件 ~~~ [config] --oltp-tables-count=10 --oltp-table-size=100000 --num-threads=8 --max-time=600 ~~~ ## 6. hashlib模块   用于加密相关的操作,3.x里代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法 ~~~ import hashlib m = hashlib.md5() m.update(b"Hello") m.update(b"It's me") print(m.digest()) m.update(b"It's been a long time since last time we ...") print(m.digest()) # 2进制格式hash ,用来代表加密后的值 print(len(m.hexdigest())) # 16进制格式hash值,用来代表加密后的值 ''' def digest(self, *args, **kwargs): # real signature unknown """ Return the digest value as a string of binary data. """ pass def hexdigest(self, *args, **kwargs): # real signature unknown """ Return the digest value as a string of hexadecimal digits. """ pass ''' import hashlib # ######## md5 ######## hash = hashlib.md5() hash.update('admin') print(hash.hexdigest()) # ######## sha1 ######## hash = hashlib.sha1() hash.update('admin') print(hash.hexdigest()) # ######## sha256 ######## hash = hashlib.sha256() hash.update('admin') print(hash.hexdigest()) # ######## sha384 ######## hash = hashlib.sha384() hash.update('admin') print(hash.hexdigest()) # ######## sha512 ######## hash = hashlib.sha512() hash.update('admin') print(hash.hexdigest()) ~~~ 还不够吊?python 还有一个 hmac 模块,它内部对我们创建 key 和 内容 再进行处理然后再加密 散列消息鉴别码,简称HMAC,是一种基于消息鉴别码MAC(Message Authentication Code)的鉴别机制。使用HMAC时,消息通讯的双方,通过验证消息中加入的鉴别密钥K来鉴别消息的真伪; 一般用于网络通信中消息加密,前提是双方先要约定好key,就像接头暗号一样,然后消息发送把用key把消息加密,接收方用key + 消息明文再加密,拿加密后的值 跟 发送者的相对比是否相等,这样就能验证消息的真实性,及发送者的合法性了。 ~~~ import hmac h = hmac.new(b'天王盖地虎', b'宝塔镇河妖') print h.hexdigest() ~~~ ## 7. subprocess模块 subprocess模块是python从2.4版本开始引入的模块。主要用来取代 一些旧的模块方法,如os.system、os.spawn*、os.popen*、commands.*等。subprocess通过子进程来执行外部指令,并通过input/output/error管道,获取子进程的执行的返回信息。 #### 7.1 subprocess.call(): subprocess.call(命令,shell=Boolean) * 执行命令,并返回执行状态,且值返回执行状态,获取不到命令的执行结果 其中shell参数为False时,命令需要通过列表的方式传入,当shell为True时,可直接传入命令 1. subprocess.call():执行命令,并返回执行状态,其中shell参数为False时,命令需要通过列表的方式传入,(命令拼接) ~~~ >>> a = subprocess.call(['df','-hT'],shell=False) Filesystem Type Size Used Avail Use% Mounted on udev devtmpfs 486M 4.0K 486M 1% /dev tmpfs tmpfs 100M 520K 99M 1% /run /dev/sda1 ext4 19G 3.3G 15G 19% / none tmpfs 4.0K 0 4.0K 0% /sys/fs/cgroup none tmpfs 5.0M 0 5.0M 0% /run/lock none tmpfs 497M 0 497M 0% /run/shm none tmpfs 100M 0 100M 0% /run/user ~~~ 2. 当shell为True时,可直接传入命令(用主机原生的shell执行命令) ~~~ >>> a = subprocess.call('ls -l',shell=True) total 160304 drwxrwxr-x 2 tuna tuna 4096 Nov 14 10:06 bzip2-1.0.6 -rw-r--r-- 1 tuna tuna 782025 Jul 31 12:59 bzip2-1.0.6.tar.gz -rw-r--r-- 1 tuna tuna 721128 Sep 13 22:26 libmysqlclient18_5.6.38-1ubuntu14.04_amd64.deb -rw-r--r-- 1 tuna tuna 1028632 Sep 13 22:26 libmysqlclient-dev_5.6.38-1ubuntu14.04_amd64.deb -rw-r--r-- 1 tuna tuna 9458512 Sep 13 22:26 libmysqld-dev_5.6.38-1ubuntu14.04_amd64.deb -rw-r--r-- 1 tuna tuna 12368 Sep 13 22:26 mysql-client_5.6.38-1ubuntu14.04_amd64.deb -rw-r--r-- 1 tuna tuna 25828 Sep 13 22:26 mysql-common_5.6.38-1ubuntu14.04_amd64.deb -rw-r--r-- 1 tuna tuna 322610 Sep 13 22:26 mysql-community-bench_5.6.38-1ubuntu14.04_amd64.deb -rw-r--r-- 1 tuna tuna 5182472 Sep 13 22:26 mysql-community-client_5.6.38-1ubuntu14.04_amd64.deb -rw-r--r-- 1 tuna tuna 10837528 Sep 13 22:26 mysql-community-server_5.6.38-1ubuntu14.04_amd64.deb -rw-r--r-- 1 tuna tuna 30170644 Sep 13 22:26 mysql-community-source_5.6.38-1ubuntu14.04_amd64.deb -rw-r--r-- 1 tuna tuna 14978548 Sep 13 22:26 mysql-community-test_5.6.38-1ubuntu14.04_amd64.deb -rw-r--r-- 1 tuna tuna 12362 Sep 13 22:26 mysql-server_5.6.38-1ubuntu14.04_amd64.deb -rw-r--r-- 1 tuna tuna 72775680 Oct 24 09:29 mysql-server_5.6.38-1ubuntu14.04_amd64.deb-bundle.tar -rw-r--r-- 1 tuna tuna 12368 Sep 13 22:26 mysql-testsuite_5.6.38-1ubuntu14.04_amd64.deb drwxr-xr-x 17 tuna tuna 4096 Nov 14 10:47 php-5.5.35 -rw-rw-r-- 1 tuna tuna 17774228 Apr 28 2016 php-5.5.35.tar.gz drwxrwxr-x 3 tuna tuna 4096 Nov 14 11:27 shell -rw-rw-r-- 1 tuna tuna 5 Nov 15 09:55 test.txt -rw-r--r-- 1 root root 2694 Feb 15 2016 zabbix-release_3.0-1+trusty_all.deb >>> print(a) 0 ~~~ #### 7.2 subprocess.check_call() 用法与subprocess.call()类似,区别是,当返回值不为0时,直接抛出异常 ~~~ >>> a = subprocess.check_call('df -hT',shell=True) Filesystem Type Size Used Avail Use% Mounted on /dev/sda2 ext4 94G 64G 26G 72% / tmpfs tmpfs 2.8G 0 2.8G 0% /dev/shm /dev/sda1 ext4 976M 56M 853M 7% /boot >>> print a 0 >>> a = subprocess.check_call('dfdsf',shell=True) /bin/sh: dfdsf: command not found Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/lib64/python2.6/subprocess.py", line 502, in check_call raise CalledProcessError(retcode, cmd) subprocess.CalledProcessError: Command 'dfdsf' returned non-zero exit status 127 ~~~ ## 7.3 subprocess.check_output(): 用法与上面两个方法类似,区别是,如果当返回值为0时,直接返回输出结果,如果返回值不为0,直接抛出异常。需要说明的是,该方法在python3.x中才有。 * 执行命令,并返回结果,注意是返回结果,不是打印,下例结果返回给res ~~~ >>> res=subprocess.check_output(['ls','-l']) >>> res b'total 0\ndrwxr-xr-x 12 alex staff 408 Nov 2 11:05 OldBoyCRM\n' ~~~ ## 7.4 subprocess.Popen(): run() 在一些复杂场景中,我们需要将一个进程的执行输出作为另一个进程的输入。在另一些场景中,我们需要先进入到某个输入环境,然后再执行一系列的指令等。这个时候我们就需要使用到suprocess的Popen()方法。该方法有以下参数: > args:shell命令,可以是字符串,或者序列类型,如list,tuple。 > bufsize:缓冲区大小,可不用关心 > stdin,stdout,stderr:分别表示程序的标准输入,标准输出及标准错误 > shell:与上面方法中用法相同 > cwd:用于设置子进程的当前目录 > env:用于指定子进程的环境变量。如果env=None,则默认从父进程继承环境变量 > universal_newlines:不同系统的的换行符不同,当该参数设定为true时,则表示使用\n作为换行符 1. 在/root下创建一个suprocesstest的目录: 在/home/tuna目录下,创建t3目录 ~~~ obj = subprocess.Popen("mkdir t3", shell=True, cwd='/home/tuna',) ~~~ ~~~ import subprocess # 把标准输入流、输出流、错误输出流都交给了subprogress obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) # 向输入流写东西 obj.stdin.write("print(1)\n") obj.stdin.write("print(2)") obj.stdin.close() # 关闭输入流 cmd_out = obj.stdout.read() # 读取输出流 obj.stdout.close() # 关闭输出流 cmd_error = obj.stderr.read() # 去取错误流 obj.stderr.close() # 关闭错流 print(cmd_out) # 打印输出 print(cmd_error) # 打印错误输出 ~~~ * sudo 密码自动输入 ~~~ import subprocess def mypass(): mypass = 'tuna' #or get the password from anywhere return mypass echo = subprocess.Popen(['echo',mypass()], stdout=subprocess.PIPE, # 把密码输出到了输出流 ) sudo = subprocess.Popen(''sudo mkdir /home/test, stdin=echo.stdout, # 把密码给输入流 stdout=subprocess.PIPE, ) end_of_pipe = sudo.stdout print "Password ok \n Iptables Chains %s" % end_of_pipe.read() ~~~ * 交互 ~~~ import subprocess obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) obj.stdin.write('print 1 \n ') obj.stdin.write('print 2 \n ') obj.stdin.write('print 3 \n ') obj.stdin.write('print 4 \n ') out_error_list = obj.communicate(timeout=10) # 提交并关闭交互 print out_error_list ~~~