python运维开发(六)----模块续

时间:2023-03-09 14:23:35
python运维开发(六)----模块续

内容目录

  • 反射
  • 模块
    • os模块
    • sys模块
    • md5加密模块
    • re正则匹配模块
    • configparse模块
    • xml模块
    • shutil模块
    • subprocess模块

反射

利用字符串的形式去对象(模块)中操作(寻找/检查/删除/设置)成员,我们称之为反射。

方法:

  1. getattr
  2. delattr
  3. setattr
  4. hasattr

应用案例需求:

现在需要访问不同的网站返回不同的数据,现在用函数和模块的方法实现该功能需求

import  commons

def run():

    inp = input('请输入要访问的url:')

    if inp == 'login':

        commons.login()

    elif inp == 'logout':

        commons.logout()

    elif inp == 'home':

        commons.home()

    else:

        print('404')

if __name__ == '__main__':

    run()

#commons.py
def home(): print('主页面') def login(): print('登录页面') def logout(): print('退出页面')

问题1:如果有我commons模块中有n多的函数,我在主程序页面中需要添加n多个if...else吗?为了处理上面的问题我们引入了映射的概念,通过字符串映射方法来实现上面的功能

import  commons

def run():

    inp = input('请输入要访问的url:')

    if hasattr(commons,inp):  #hasattr判断是否在commons模块中存在inp的方法

        func = getattr(commons,inp) #通过字符串inp来匹配comons模块中的方法

        func()

    else:

        print('404')  #不存在返回404

if __name__ == '__main__':

    run()

问题2:如果我的方法不在同一个commons模块中,存在多个模块中,并且每个模块中有不同的方法,如何访问呢?我们可以通过__import__字符串匹配模块加字符串匹配方法来实现

目录结构如下,其中模块中为类似上面commons中简单函数account/login,account/logout,commons/home,order/order

python运维开发(六)----模块续

具体实现代码:

def run():

    inp = input('请输入要访问的url(account/login格式):')

    m,f = inp.split('/')

    obj = __import__("lib."+m,fromlist=True)

    if hasattr(obj,f):

        func = getattr(obj,f)

        func()

    else:

        print('404')

if __name__ == '__main__':

    run()

模块

python的几个特殊变量

__doc__ 输出python的注释内容

"""
注释功能 """ print(__doc__) #输出: 注释功能

__file__ 当前py文件的路径,是相对路径

一般配合os.path.abspath使用找到当前程序的绝对路径

import  os

current_url = os.path.abspath(__file__)

print(current_url)

#输出

E:\python\s13\test\test.py

扩展获取当前路径的上一级或者上两级目录路径

import os

import sys

print(os.path.abspath(__file__)) #当前py的绝对路径

print(os.path.dirname(os.path.abspath(__file__))) #当前目录上一级目录

print(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) #当前目录上上一级目录

sys.path.append((os.path.dirname(os.path.abspath(__file__)))) #添加到系统环境变量中

#输出
E:\python\s13\test\test.py E:\python\s13\test E:\python\s13

__packaged__ 为模块的集合包,通过导入模块可以更容易理解

from lib import account

print(account.__package__)

print(__package__)

#输出

lib #account属于lib包下面的方法

None

__cached__ python的缓存,导入模块后在当前目录下就会生成__pycache__目录
__name__ 一般与__main__连用

__name__= __main__ 表示调用当前函数的主函数,执行下面的函数体,如果作为模块导入的话下面的函数体不执行

os模块

用于提供系统级别的操作

常用的功能方法:

os.path.abspath(path) 返回path规范化的绝对路径

os.path.dirname(path) 返回path的上一级目录,其实就是os.path.split(path)的第一个元素

os.path.join(path1[, path2[, ...]])  将多个路径组合后返回,第一个绝对路径之前的参数将被忽略

current_file = os.path.abspath(__file__) #当前文件的绝对路径
current_dir = os.path.dirname(current_file) #当前文件所在目录
print(current_dir)
lib_dir = os.path.join(current_dir,'lib') #拼接lib目录
test_dir = os.path.join(current_dir,'lib','test') #拼接lieb和test目录
print(lib_dir)
print(test_dir) #输出
E:\python\s13\test
E:\python\s13\test\lib
E:\python\s13\test\lib\test

其他一些os功能:

os.getcwd()                 获取当前工作目录,即当前python脚本工作的目录路径
os.chdir("dirname") 改变当前脚本工作目录;相当于shell下cd
os.curdir 返回当前目录: ('.')
os.pardir 获取当前目录的父目录字符串名:('..')
os.makedirs('dir1/dir2') 可生成多层递归目录
os.removedirs('dirname1') 若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
os.mkdir('dirname') 生成单级目录;相当于shell中mkdir dirname
os.rmdir('dirname') 删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname
os.listdir('dirname') 列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
os.remove() 删除一个文件
os.rename("oldname","new") 重命名文件/目录
os.stat('path/filename') 获取文件/目录信息
os.sep 操作系统特定的路径分隔符,win下为"\\",Linux下为"/"
os.linesep 当前平台使用的行终止符,win下为"\t\n",Linux下为"\n"
os.pathsep 用于分割文件路径的字符串
os.name 字符串指示当前使用平台。win->'nt'; Linux->'posix'
os.system("bash command") 运行shell命令,直接显示
os.environ 获取系统环境变量
os.path.abspath(path) 返回path规范化的绝对路径
os.path.split(path) 将path分割成目录和文件名二元组返回
os.path.dirname(path) 返回path的目录。其实就是os.path.split(path)的第一个元素
os.path.basename(path) 返回path最后的文件名。如何path以/或\结尾,那么就会返回空值。即os.path.split(path)的第二个元素
os.path.exists(path) 如果path存在,返回True;如果path不存在,返回False
os.path.isabs(path) 如果path是绝对路径,返回True
os.path.isfile(path) 如果path是一个存在的文件,返回True。否则返回False
os.path.isdir(path) 如果path是一个存在的目录,则返回True。否则返回False
os.path.join(path1[, path2[, ...]]) 将多个路径组合后返回,第一个绝对路径之前的参数将被忽略
os.path.getatime(path) 返回path所指向的文件或者目录的最后存取时间
os.path.getmtime(path) 返回path所指向的文件或者目录的最后修改时间

sys模块

用于提供python解释器相关的操作

常用功能方法

sys.argv           命令行参数List,第一个元素是程序本身路径
sys.exit(n) 退出程序,正常退出时exit(0)
sys.version 获取Python解释程序的版本信息
sys.maxint 最大的Int值
sys.path 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
sys.platform 返回操作系统平台名称
sys.stdin 输入相关
sys.stdout 输出相关
sys.stderror 错误相关

sys模块应用,百分比进度条显示

def view_bar(num, total):

    rate = float(num) / float(total)

    rate_num = int(rate * 100)

    r = '\r%s>%d%%' % ('='*num,rate_num, ) #\r表示置前显示

    sys.stdout.write(r)

    sys.stdout.flush()

if __name__ == '__main__':

    for i in range(0, 101):

        time.sleep(0.1)

        view_bar(i, 100)

md5加密模块

用于加密相关的操作,代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法

MD5模块应用

import hashlib

obj = hashlib.md5()

obj.update(bytes('123',encoding='utf-8'))

resault = obj.hexdigest()

print(resault)

结果:

202cb962ac59075b964b07152d234b70

通过以上方式可以对123等字符串进行加密,但是通过撞库可以反解,我们可以自定义key来添加一层加密

import hashlib

obj = hashlib.md5(bytes('jabe',encoding='utf-8')) #加上key值来做md5加密

obj.update(bytes('123',encoding='utf-8'))

resault = obj.hexdigest()

print(resault)

结果:

21b461551c9cecdc295baaa8a9002076

其他一些算法的应用

import hashlib

# ######## md5 ########
hash = hashlib.md5()
# help(hash.update)
hash.update(bytes('admin', encoding='utf-8'))
print(hash.hexdigest())
print(hash.digest()) ######## sha1 ########
hash = hashlib.sha1()
hash.update(bytes('admin', encoding='utf-8'))
print(hash.hexdigest()) # ######## sha256 ########
hash = hashlib.sha256()
hash.update(bytes('admin', encoding='utf-8'))
print(hash.hexdigest()) # ######## sha384 ########
hash = hashlib.sha384()
hash.update(bytes('admin', encoding='utf-8'))
print(hash.hexdigest()) # ######## sha512 ########
hash = hashlib.sha512()
hash.update(bytes('admin', encoding='utf-8'))
print(hash.hexdigest())

re正则匹配模块

python中re模块提供了正则表达式相关操作

字符:

  • . 匹配除换行符以外的任意字符
  • \w匹配字母或数字或下划线或汉字
  • \s匹配任意的空白符
  • \d匹配数字
  • \b匹配单词的开始或结束
  • ^匹配字符串的开始
  • $匹配字符串的结束

次数:

  • * 重复零次或更多次
  • + 重复一次或更多次
  • ?重复零次或一次
  • {n} 重复n次
  • {n,}重复n次或更多次
  • {n,m}重复n到m次

match

# match,从起始位置开始匹配,匹配成功返回一个对象,未匹配成功返回None

 match(pattern, string, flags=0)
# pattern: 正则模型
# string : 要匹配的字符串
# falgs : 匹配模式
X VERBOSE Ignore whitespace and comments for nicer looking RE's.
I IGNORECASE Perform case-insensitive matching.
M MULTILINE "^" matches the beginning of lines (after a newline)
as well as the string.
"$" matches the end of lines (before a newline) as well
as the end of the string.
S DOTALL "." matches any character at all, including the newline. A ASCII For string patterns, make \w, \W, \b, \B, \d, \D
match the corresponding ASCII character categories
(rather than the whole Unicode categories, which is the
default).
For bytes patterns, this flag is the only available
behaviour and needn't be specified. L LOCALE Make \w, \W, \b, \B, dependent on the current locale.
U UNICODE For compatibility only. Ignored for string patterns (it
is the default), and forbidden for bytes patterns.

分组方式

 # 无分组
r = re.match("h\w+", origin)
print(r.group()) # 获取匹配到的所有结果
print(r.groups()) # 获取模型中匹配到的分组结果
print(r.groupdict()) # 获取模型中匹配到的分组结果 # 有分组 # 为何要有分组?提取匹配成功的指定内容(先匹配成功全部正则,再匹配成功的局部内容提取出来) r = re.match("h(\w+).*(?P<name>\d)$", origin)
print(r.group()) # 获取匹配到的所有结果
print(r.groups()) # 获取模型中匹配到的分组结果
print(r.groupdict()) # 获取模型中匹配到的分组中所有执行了key的组

search

search,浏览整个字符串去匹配第一个,未匹配成功返回None

语法:search(pattern, string, flags=0)

# 无分组
r = re.search("a\w+", origin)
print(r.group()) # 获取匹配到的所有结果
print(r.groups()) # 获取模型中匹配到的分组结果
print(r.groupdict()) # 获取模型中匹配到的分组结果
# 有分组
r = re.search("a(\w+).*(?P<name>\d)$", origin)
print(r.group()) # 获取匹配到的所有结果
print(r.groups()) # 获取模型中匹配到的分组结果
print(r.groupdict()) # 获取模型中匹配到的分组中所有执行了key的组

findall

获取非重复的匹配列表;如果有一个组则以列表形式返回,且每一个匹配均是字符串;如果模型中有多个组,则以列表形式返回,且每一个匹配均是元组;

空的匹配也会包含在结果中;

语法:findall(pattern, string, flags=0)

功能用法:

# 无分组

r = re.findall("a\w+",origin)

print(r)

# 有分组

origin = "hello alex bcd abcd lge acd 19"

r = re.findall("a((\w*)c)(d)", origin)

print(r)

sub

sub,替换匹配成功的指定位置字符串
sub(pattern, repl, string, count=0, flags=0)
pattern: 正则模型
repl : 要替换的字符串或可执行对象
string : 要匹配的字符串
count : 指定匹配个数
flags : 匹配模式

应用:

# 与分组无关

origin = "hello alex bcd alex lge alex acd 19"

r = re.sub("a\w+", "999", origin, 2)

print(r)

split

split,根据正则匹配分割字符串
split(pattern, string, maxsplit=0, flags=0)
pattern:正则模型
string:要匹配的字符串
maxsplit:指定分割个数
flags:匹配模式

应用:

# 无分组
origin = "hello alex bcd alex lge alex acd 19" r = re.split("alex", origin, 1) print(r) # 有分组
origin = "hello alex bcd alex lge alex acd 19" r1 = re.split("(alex)", origin, 1) print(r1) r2 = re.split("(al(ex))", origin, 1) print(r2)

常用正则匹配

IP:
^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$ 手机号:
^1[3|4|5|8][0-9]\d{8}$ 邮箱:
[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+

configparse模块

configparser模块用于处理特殊格式的文件本质上是open对文件的操作。

格式类型如下:

[section1] #格式为[]

k1 = 123 #key和value对应的值格式

k2 = v2

[section2]

k1 = v1

功能方法应用:

1、获取所有节点

import  configparser

config = configparser.ConfigParser() #调用模块中的方法ConfigParser

config.read('testfile',encoding='UTF-8')#读取文件

ret = config.sections() #获取所有节点名称

print(ret) #打印取到的结果

#输出
['section1', 'section2', 'section4']

testfile文件

[section1]

k1 = 123

k2 = v2

[section2]

k1 = v1

2、获取指定节点下所有的键值对

import  configparser

config = configparser.ConfigParser()

config.read('testfile',encoding='UTF-8')

ret = config.items('section1') #获取section1下面所有的键值对

print(ret)

#输出

[('k1', '123'), ('k2', 'v2')]

3、获取指定节点下所有的key值

ret = config.options('section1') #获取section1下面的key

#输出:

['k1', 'k2']

4、获取指定节点下key对应得value值

ret = config.get('section1','k1') #获取section1节点下面k1对应的value值

#将获取到的k1对应的value值转为int类型,不为数字的话抛出异常
ret1 = config.getint('section1', 'k1') #将获取到的k1对应的value值转为float类型,不能转的话抛出异常
ret2 = config.getfloat('section1', 'k1') #将获取到的k1对应的value值转为布尔类型,不能转抛出异常
ret3 = config.getboolean('section2', 'k2') print(ret,ret1,ret2,ret3) #输出:
123 123 123.0 True

5、检查添加删除节点

# 检查

has_sec = config.has_section('section1')

print(has_sec)

#输出

True

#添加节点

config.add_section('section4') #在内存中添加节点section4

config.write(open('testfile','w')) #写入文件

#删除节点

config.remove_section('section4') #删除section4节点在内存中

config.write(open('testfile','w')) #文件中删除section4节点

has_sec = config.has_section('section4')#判断是否还存在section4节点

print(has_sec) 

#输出:False

6、检查删除设置指定组内的键值对

#检查

has_opt = config.has_option('section1','k1')

print(has_opt)

# 删除

config.remove_option('section1', 'k1')

config.write(open('testfile', 'w'))

# 设置

config.set('section1', 'k1', "123")

config.write(open('testfile', 'w'))

XML模块

XML是实现不同语言或程序之间进行数据交换的协议

通常访问浏览器返回的字符串有HTML和JSON和XML三种格式,

XML主要应用

1 在页面上做展示(字符串类型的一个xml格式数据),

2 配置文件(操作的文件内部的xml数据格式)

格式如下:

<data>
<country name="Liechtenstein">
<rank updated="yes">2</rank>
<year>2023</year>
<gdppc>141100</gdppc>
<neighbor direction="E" name="Austria" />
<neighbor direction="W" name="Switzerland" />
</country>
<country name="Singapore">
<rank updated="yes">5</rank>
<year>2026</year>
<gdppc>59900</gdppc>
<neighbor direction="N" name="Malaysia" />
</country>
<country name="Panama">
<rank updated="yes">69</rank>
<year>2026</year>
<gdppc>13600</gdppc>
<neighbor direction="W" name="Costa Rica" />
<neighbor direction="E" name="Colombia" />
</country>
</data>

1 解析xml

利用ElementTree.XML将字符串解析成xml对象

from xml.etree import ElementTree as ET

# 打开文件,读取XML内容
str_xml = open('xo.xml', 'r').read() # 将字符串解析成xml特殊对象,root代指xml文件的根节点
root = ET.XML(str_xml)

利用ElementTree.parse将文件直接解析成xml对象

from xml.etree import ElementTree as ET

# 直接解析xml文件
tree = ET.parse("xo.xml") # 获取xml文件的根节点
root = tree.getroot()

2、操作xml

a 遍历xml文档内所有的内容

from xml.etree import  ElementTree as ET

tree = ET.parse('xo.xml') #直接解决xml文件

root = tree.getroot() #获取root根节点

print(root) #root为对象类型

for child in root:

    print(child.tag,child.attrib) #child.tag二级节点标签,child.attrib二级节点属性

    for grandchild in child:

        print(grandchild.tag,grandchild.text) #grandchild.text三级节点内容

b 遍历xml指定节点的节点

字符串解析方式
# 打开文件,读取XML内容
str_xml = open('xo.xml', 'r').read() # 将字符串解析成xml特殊对象,root代指xml文件的根节点
root = ET.XML(str_xml)
print(root.tag) #解析文件方式
from xml.etree import ElementTree as ET
tree = ET.parse('xo.xml')
root = tree.getroot() #顶层标签
print(root.tag) # 遍历XML中所有的year节点 #iter为在当前节点的子孙中根据节点名称寻找所有指定的节点,并返回一个迭代器(可以被for循环)
for node in root.iter('year'):
# 节点的标签名称和内容
print(node.tag, node.text)

c 修改节点、删除、保存文件

#解析字符串方式,修改,保存
from xml.etree import ElementTree as ET
# str_xml = open('xo.xml','r').read()
# root = ET.XML(str_xml) #解析xml文件方式
tree = ET.parse('xo.xml')
root = tree.getroot() print(root.tag)
for node in root.iter('year'):
new_year = int(node.text) +1
node.text = str(new_year)
node.set('name','jabe')
node.set('age','18') # 删除属性
#del node.attrib['name'] # 遍历data下的所有country节点
for country in root.findall('country'):
# 获取每一个country节点下rank节点的内容
rank = int(country.find('rank').text) if rank > 50:
# 删除指定country节点
root.remove(country) # 保存文件
tree = ET.ElementTree(root)
tree.write("new.xml", encoding='utf-8')

c 创建xml文档(默认创建的xml文档是不带格式缩进的)

from xml.etree import ElementTree as ET
#创建根节点
root = ET.Element("famliy")
#创建节点大儿子
son1 = ET.Element('son',{'name':'儿1'})
son2 = ET.Element('son',{'name':'儿2'})
# 在大儿子中创建两个孙子
grandson1 = ET.Element('grandson', {'name': '儿11'})
grandson2 = ET.Element('grandson', {'name': '儿12'})
son1.append(grandson1)
son1.append(grandson2) # 把儿子添加到根节点中
root.append(son1)
root.append(son1) tree = ET.ElementTree(root)
tree.write('oo.xml',encoding='utf-8', short_empty_elements=False)

如果要格式化输出加上缩进的话需要添加一个函数如下:

from xml.etree import ElementTree as ET
from xml.dom import minidom def prettify(elem):
"""将节点转换成字符串,并添加缩进。
"""
rough_string = ET.tostring(elem, 'utf-8')
reparsed = minidom.parseString(rough_string)
return reparsed.toprettyxml(indent="\t")
# 创建根节点
root = ET.Element("famliy") # 创建大儿子
# son1 = ET.Element('son', {'name': '儿1'})
son1 = root.makeelement('son', {'name': '儿1'})
# 创建小儿子
# son2 = ET.Element('son', {"name": '儿2'})
son2 = root.makeelement('son', {"name": '儿2'}) # 在大儿子中创建两个孙子
# grandson1 = ET.Element('grandson', {'name': '儿11'})
grandson1 = son1.makeelement('grandson', {'name': '儿11'})
# grandson2 = ET.Element('grandson', {'name': '儿12'})
grandson2 = son1.makeelement('grandson', {'name': '儿12'}) son1.append(grandson1)
son1.append(grandson2) # 把儿子添加到根节点中
root.append(son1)
root.append(son1) raw_str = prettify(root) f = open("oo.xml",'w',encoding='utf-8')
f.write(raw_str)
f.close()

shutil模块

高级的文件、文件夹、压缩包处理模块

shutil.copyfileobj(fsrc, fdst[, length])

将文件内容拷贝到另一个文件中

import shutil

shutil.copyfileobj(open('xo.xml','r'),open('xo_bak.xml','w'))

shutil.copyfile(src, dst)

拷贝文件

 shutil.copyfile('x1.xml', 'x2.xml')

shutil.copymode(src, dst)
仅拷贝权限。内容、组、用户均不变

shutil.copymode('x1.xml', 'x3.xml')

shutil.copystat(src, dst)
仅拷贝状态的信息,包括:mode bits, atime, mtime, flags

shutil.copystat('x1.xml', 'x2.xml')

shutil.copy(src, dst)
拷贝文件和权限

shutil.copy('x1.xml', 'x2.xml')

shutil.copy2(src, dst)
拷贝文件和状态信息  

import shutil

shutil.copy2('x1.xml', 'x2.xml')

shutil.ignore_patterns(*patterns)
shutil.copytree(src, dst, symlinks=False, ignore=None)
递归的去拷贝文件夹

import shutil

shutil.copytree('folder1', 'folder2', ignore=shutil.ignore_patterns('*.pyc', 'tmp*'))

#folder1拷贝为folder2忽略其中的*.pyc结尾文件和tmp开头的文件

import shutil

shutil.copytree('f1', 'f2', symlinks=True, ignore=shutil.ignore_patterns('*.pyc', 'tmp*'))

shutil.rmtree(path[, ignore_errors[, onerror]])
递归的去删除文件

import shutil

shutil.rmtree('folder1')

shutil.move(src, dst)
递归的去移动文件,它类似mv命令,其实就是重命名。

shutil.move('folder1', 'folder3')

shutil.make_archive(base_name, format,...)

创建压缩包并返回文件路径,例如:zip、tar

    • base_name: 压缩包的文件名,也可以是压缩包的路径。只是文件名时,则保存至当前目录,否则保存至指定路径,
      如:www                        =>保存至当前路径
      如:/Users/wupeiqi/www =>保存至/Users/wupeiqi/
    • format: 压缩包种类,“zip”, “tar”, “bztar”,“gztar”
    • root_dir: 要压缩的文件夹路径(默认当前目录)
    • owner: 用户,默认当前用户
    • group: 组,默认当前组
#将 /Users/wupeiqi/Downloads/test 下的文件打包放置当前程序目录
import shutil
ret = shutil.make_archive("wwwwwwwwww", 'gztar', root_dir='/Users/wupeiqi/Downloads/test') #将 /Users/wupeiqi/Downloads/test 下的文件打包放置 /Users/wupeiqi/目录
import shutil
ret = shutil.make_archive("/Users/wupeiqi/wwwwwwwwww", 'gztar', root_dir='/Users/wupeiqi/Downloads/test')

shutil 对压缩包的处理是调用 ZipFile 和 TarFile 两个模块来进行的

zipfile解压缩

import zipfile
#压缩
z = zipfile.ZipFile('test.zip','w')
z.write('testfile')
z.write('xo.xml')
z.close()
#解压
z = zipfile.ZipFile('test.zip','r')
for item in z.namelist(): #namelist查看压缩文件内的文件列表
print(item)
z.close()
z.extract('testfile') #解压指定文件
z.extractall() #解压所有文件
z.close()

tarfile解压缩

import  tarfile
#压缩
tar = tarfile.open('test.tar','w')
tar.add('xo.xml',arcname='x1.xml')
tar.add('testfile',arcname='testfile1')
tar.close() #解压
tar = tarfile.open('test.tar','r')
#tar.extractall() #
# for item in tar.getmembers():
# print(item)
obj = tar.getmember('x1.xml')
tar.extract(obj)
tar.close()

subprocess模块

执行系统命令模块

call方法

执行命令,返回状态码

import subprocess

ret = subprocess.call(["ls", "-l"], shell=False)#shell为false前面参数为列表

ret = subprocess.call("ls -l", shell=True)#shell为true,前面参数为字符串

check_call方法

执行命令,如果执行状态码是 0 ,则返回0,否则抛异常

subprocess.check_call(["ls", "-l"])

subprocess.check_call("exit 1", shell=True)

check_output方法

执行命令,如果状态码是 0 ,则返回执行结果,否则抛异常

subprocess.check_output(["echo", "Hello World!"])

subprocess.check_output("exit 1", shell=True)

subprocess.Popen(...)

用于执行复杂的系统命令

参数:

    • args:shell命令,可以是字符串或者序列类型(如:list,元组)
    • bufsize:指定缓冲。0 无缓冲,1 行缓冲,其他 缓冲区大小,负值 系统缓冲
    • stdin, stdout, stderr:分别表示程序的标准输入、输出、错误句柄
    • preexec_fn:只在Unix平台下有效,用于指定一个可执行对象(callable object),它将在子进程运行之前被调用
    • close_sfs:在windows平台下,如果close_fds被设置为True,则新创建的子进程将不会继承父进程的输入、输出、错误管道。
      所以不能将close_fds设置为True同时重定向子进程的标准输入、输出与错误(stdin, stdout, stderr)。
    • shell:同上
    • cwd:用于设置子进程的当前目录
    • env:用于指定子进程的环境变量。如果env = None,子进程的环境变量将从父进程中继承。
    • universal_newlines:不同系统的换行符不同,True -> 同意使用 \n
    • startupinfo与createionflags只在windows下有效
      将被传递给底层的CreateProcess()函数,用于设置子进程的一些属性,如:主窗口的外观,进程的优先级等等

执行mkdir命令两种方式

import subprocess

ret1 = subprocess.Popen(["mkdir","t1"]) #列表方式

ret2 = subprocess.Popen("mkdir t2", shell=True) #shell为true字符串方式

终端输入的命令分为两种:

  • 输入即可得到输出,如:ifconfig
  • 输入进行某环境,依赖再输入,如:python
obj = subprocess.Popen("mkdir t3", shell=True, cwd='/home/dev',)

#先进入到/home/dev下执行mkdir t3命令

将python命令输入到管道,在从管道一行一行读取出来

import subprocess

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)

将python命令输入到管道,在从管道通过communicat方法计算写入到列表中

import subprocess

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)") out_error_list = obj.communicate()
print(out_error_list)

  

import subprocess

obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
out_error_list = obj.communicate('print("hello")')
print(out_error_list)

参考url:

http://www.cnblogs.com/wupeiqi/articles/5501365.html