Python自动化运维 - day6 - 常用模块

re模块

  re模块,包含所有正则表达式的功能,可以使用正则表达式对字符串进行匹配过滤的,那么先来看一下正则表达式。

正则表达式

正则表达式是一种用来匹配字符串的强有力的武器。它的设计思想是用一种描述性的语言来给字符串定义一个规则,凡是符合规则的字符串,我们就认为它“匹配”了,否则,该字符串就是不合法的。

常用的规则如下表所示:

符号含义
\w字母、数字、下划线
\W非字母、数字、下划线
\s任意空白字符串,等价于[\t\n\r\f]
\S任意非空字符串
\d任意数字,等价于[0-9]
\D任意非数字
\n换行符(在windows下换行符为\r\n)
\t制表符
^字符串的开头
$字符串的结尾
.任意单个字符串,但是\n等是无法匹配到的,findall指定参数re.S(可以让.匹配到换行符)
[...]用来表示一组,一个范围[a-c],等于a,b,c
*表示前面的字符出现0次或者N次(前边可以是字符也可以是一个正则表达式)
表示前面的字符出现1次或者多次(前边可以是字符也可以是一个正则表达式)
?匹配前面的字符或表达式,出现0次或者1次
{n}表示前面的字符出现n次
{n,m}表示前面的字符串最少出现n次,最多出现m次
.*表示匹配任意长度的字符串(贪婪匹配)
.*?表示匹配任意长度的字符串(非贪婪匹配),
a|b匹配a或b,如果匹配到a就不会继续匹配b,没有匹配到a才会继续匹配b
()分组,这样只会返回分组里面的内容,就算后面有其他表达式也不会返回,在括号里面用?: 内部表示不单纯匹配括号里面的内容
compan(?:y|ies)等于 company | companie

 

 更多常用的正则表达式在线转换工具:tool.oschina.net/regex/#

功能函数

re.findall(expression,val)
  从val的左边进行查找,查找所有expression匹配到的字符串,并用list进行存储

例子:匹配所有的数字
                s = '1-2*(60+(-40.35/5.3+1.2)-(-4*3))'
                num = re.findall('\-?\d+\.?\d*',s)  #会匹配所有数字,包涵正负数,小数等

扩展:re.findall(r'\-?\d+\.\d+|(\-?\d+)','1-2*(60+(-40.35/5.3+1.2)-(-4*3))')   
                由于使用了(),既只显示()里面匹配到的元素,既只匹配到了正负整数
View Code

re.search(expression,val)
  从value的左边进行查找,查找匹配expression的对象,找到1个既返回,找到则返回SRE对象,找不到就返回None,通过对象的.group()方法读取匹配到的信息

例子:匹配数字
s = '1-2*(60+(-40.35/5.3+1.2)-(-4*3))'
num = re.search('\-?\d+\.?\d*',s).group() #会匹配到第一个数字1,
扩展:re.search('exp1|exp2',val) 同时拿着exp1,exp2去val中匹配,满足任意一个,则返回
s = '1.3-2*(60+(-40.35/5.3+1.2)-(-4*3))'
num = re.search('\-?\d+\.\d+|\-?\d+',s).group() #匹配正负整数或者正负小数,任意一个匹配到则返回
View Code

re.match(expression,val)
  从value开头开始找,匹配则返回SRE对象,不匹配就返回None,功能类似于 ^

例子:匹配a
s = 'daxin like Linux'
match = re.match('a',s) #返回None,re.match('d',s)则返回d
View Code

group()
  对表达式进行分组

re.search('al(e)x mak(e)','alex make love').group() 结果类似于findall里面的 ?: ,如果 group(1),则会匹配到底一个()里面的e,group(2),则会匹配到第二个()里面的e。    
group(int) int 表示匹配到的第几个括号的内容,如果不指定,则显示所有匹配到字符串
例子:
re.search('al(e)x mak(e)','alex make love').group() #结果:alex make
re.search('al(e)x mak(e)','alex make love').group(1) #结果: e
View Code

re.split(expression,val)
  把val按照expression进行分割,支持按照正则表达式进行分割,返回list

例子:针对数字进行分隔
s = r'9+63+2-(12*2)/9'
list1 = re.split('[0-9]',s) #结果:['', '+', '', '+', '-(', '', '*', ')/', '']
View Code

re.sub('sub1','sub2',string)
  把字符串中的sub1,替换为sub2

例子:
s = r'1.3-2*(60+(-40.35/5.3+1.2)-(-4*3))'
match = re.sub('-','A',s) #把-号,替换为A

扩展:
re.sub('(\w+)(\s)(\w+)(\s)(\w)$',r'\5\2\3\4\1','alex make love')
字符串换位,后面的数字表示前面括号匹配到的字符串,类似于Linxu下的sed命令
View Code

time模块

  时间戳: time.time()
    从1970年开始(unix元年),的秒数
  结构化时间: time.localtime() #当前时区 UTC时区time.gmtime()
    元祖的形式显示时间(time.localtime().tm_year()获取年,)
  格式化时间: time.strftime('%Y-%m-%d %H:%M:%S')
    %X 效果等同于 %H:%M:%S

  转换关系:

#时间戳
print(time.time())
#时间戳转换为结构化时间
print(time.localtime(time.time()))
#时间戳转换为格式化时间(时间戳不能直接转换为格式化时间,需要使用结构化时间中继)
print(time.strftime('%Y-%m-%d',time.localtime(time.time())))

#结构化时间
print(time.localtime())
#结构化时间转换为时间戳
print(time.mktime(time.localtime()))
#结构化时间转换为格式化时间
print(time.strftime('%Y-%m-%d',time.localtime()))

#格式化时间
print(time.strftime('%Y-%m-%d %X'))
#格式化时间转换为结构化时间
print(time.strptime('2017-06-04','%Y-%m-%d'))
#格式化时间转换为时间戳(格式化时间不能直接转换为时间戳,需要使用结构化时间中继)
print(time.mktime(time.strptime(time.strftime('%Y-%m-%d'),'%Y-%m-%d')))

random模块

  主要用来产生随机数

random.random() 0和1之间的小数

>>> random.random()
0.37989514876249375
>>> random.random()
0.3337038388412016
>>> 
View Code

random.randint(1,3) 取出1-3之间的整数,包含1,3

>>> random.randint(1,10)
4
>>> random.randint(1,10)
9
>>> random.randint(1,10)
1
>>> 
View Code

random.randrange(1,3) 取出1-3之间的整数,和普通 range 用法相同,顾前不顾后. (包含1不包含3)

>>> random.randrange(1,4)
2
>>> random.randrange(1,4)
1
>>> random.randrange(1,4)
2
>>> 
View Code

random.choice(iterable) 随机在iterable中去随机抽取一个对象

>>> random.choice([1,2,3,4,5,6])
1
>>> random.choice([1,2,3,4,5,6])
4
>>> random.choice([1,2,3,4,5,6])
3
>>> 
View Code

random.sample(iterable,int) 每次在iterable对象中选取 int 个元素,组成列表并返回

>>> random.sample([1,2,3,4,5,6,7,8],3)
[2, 8, 4]
>>> random.sample([1,2,3,4,5,6,7,8],3)
[4, 7, 8]
>>> random.sample([1,2,3,4,5,6,7,8],3)
[1, 6, 8]
>>> 
View Code

random.uniform(1,3) 随机选出1和3之间的小数

>>> random.uniform(1,2)
1.343193035913123
>>> random.uniform(1,2)
1.8532874990121724
>>> random.uniform(1,2)
1.960351385197145
>>> 
View Code

random.shuffle(itarable) 把 iterable 对象 的顺序进行打乱(洗牌)

>>> a = [ i for i in range(100)]
>>> random.shuffle(a)
>>> a
[46, 24, 48, 17, 50, 10, 34, 90, 29, 33, 85, 21, 71, 14, 78, 58, 55, 54, 45, 12, 60, 70, 66, 73, 95, 23, 59, 69, 68, 35, 88, 93, 53, 84, 61, 36, 82, 30, 31, 20, 56, 64, 4, 40, 42, 32, 7, 77, 27, 22, 1, 74, 28, 19, 96, 8, 94, 80, 2, 9, 16, 44, 57, 11, 41, 92, 5, 43, 83, 81, 37, 47, 15, 86, 6, 13, 89, 87, 79, 98, 38, 72, 99, 51, 63, 26, 0, 18, 67, 3, 91, 25, 97, 62, 76, 75, 65, 52, 49, 39]
>>> 
View Code

注意:会直接作用在iterabel对象上,不会产生副本

例子:编写随机验证码

 1 import random
 2 
 3 def check(n):
 4     code = ''
 5     for i in range(n):
 6         num = random.randint(1,9)
 7         s = chr(random.randint(65,90))
 8         add = random.choice([num,s])
 9         code += str(add)
10 return code
11 
12 print(check(3))    

os模块

os.getcwd():获取当前路径
os.chdir():切换当前目录,当路径中存在\的时候,由于是转意的意思,那么就需要对\进行转意,那么路径就是c:\\User,或者在目录前面加r,表示后面的字符串不进行解释
os.curdir():获取当前目录名
os.pardir():获取上级目录名
os.mkdir('dir'):创建目录,注意只能创建一级目录
os.makedirs('dir_path'):创建多级目录
os.rmdir('dir'):删除一个目录
os.removedir('dir_path'):删除多级目录(目录为空的话)
os.listdir('dir'):显示目录下的所有文件,默认为当前目录,返回的结果为list
os.remove('file'):删除一个文件
os.rename('old_name','new_name'):修改文件名称
os.stat('file/dir'):获取文件/目录的stat信息
os.sep:返回当前操作系统的路径分隔符
Windows下:\\ , Linux下:/
os.linesep:返回当前操作系统的换行符
Windows下:\r\n  ,Linux下:\n
os.pathsep:返回当前操作系统环境变量分隔符
Windows下:;   ,   Linux下: :
os.name:返回当前系统的类型
nt 表示Windows,  posix表示Linux
os.system('Commmand'):执行命令
os.environ:获取系统环境变量,使用字典存储
os.path.abspath('dir/file'):获取dir/file的绝对路径
os.path.split('path'):把路径分割为目录和文件名组成的元组格式,不管path是否存在
os.dirname('path'):获取文件的父目录名称,不管path是否存在
os.basename('path'):获取文件的名称,不管path是否存在
os.path.exists('path'):判断path是否存在,return bool
os.path.isabs('path'):判断path是否是从根开始,return bool
Linux下:从/开始    Windows下从C,D,E盘开始
os.path.isfile('path'):判断path是否是一个文件
os.path.isdir('path'):判断path是否是一个目录
os.path.join('path1','path2','path3'):把path1和path2及path3进行组合,但如果path2中包含了根路径,那么就会舍弃path1,从path2开始组合
os.path.getatime('path'):获取文件的atime时间,返回时间戳
os.path.getmtime('path'):获取文件的mtime时间,返回时间戳
os.path.getsize(filename): 获取文件的大小,单位是字节

os.walk

  日常的工作中,可能常常需要使用查找某个目录下的符合某些规则的文件,并且可能是递归查询,对于这类需求可以使用os.walk模块。

  walk函数便利某个目录及其子目录,对于每一个目录,os.walk返回一个三元组(dirpath,dirnames,filenames)。

    • dirname:表示目录名
    • dirnames:表示目录下的子目录名称
    • filenames:表示目录下的文件名
>>> name = os.walk('/Users/DahlHin/Python')  # 返回的是一个生成器
>>> for roots,dirs,filenames in name:
	for file in filenames:
		filename = os.path.join(roots,file)
		file_list.append(filename)

# file_list 则存储了Python目录下的所有文件

列出目录下所有以.txt结尾的文件

>>> 
>>> import fnmatch
>>> import os
>>> file_list = []
>>> name = os.walk('/Users/DahlHin/Python')
>>> for roots,dirs,files in name:
	for file in files:
		filename = os.path.join(roots,file)
		if fnmatch.fnmatch(filename,"*.txt"):
			file_list.append(filename)		
>>> file_list

sys模块

sys.argv  命令行参数List,第一个元素是程序本身路径(空表示当前目录)
sys.exit(n)  退出程序,如果n为数字的话,那么就是 echo $?的值,如果是 str,那么会直接打印在屏幕上
sys.version  获取python解释器的版本信息
sys.maxint  获取当前操作系统最大的int值(2.x的时候,32位主机和64为主机int值范围不同) --> python 2
sys.path  Python的初始环境变量
sys.platform  返回操作系统的平台名称
sys.stdout  标准输出(其实就是屏幕,本质上标注你输出也是一个文件,也有write方法)
sys.stdout.write('str')  把 str 写到标准输出中去 注意:'\r'跳到行首

PS:在sys.path中添加当前目录,可以让Python解释器,在当前目录寻找模块,或者包,不过还有另一种方法是设置环境变量PYTHONPATH,该环境变量的内容会被自动添加到模块搜索路径中。设置方式与设置Path环境变量类似。注意只需要添加你自己的搜索路径,Python自己本身的搜索路径不受影响。

shutil模块

shutil.copyfileobj(fsrc,fdes,length)  将文件内容拷贝到另一个文件中,可以只拷贝部分内容,需要我们自行打开文件对象进行copy

>>> import os,shutil
>>> os.system('ls')
1.txt
>>> shutil.copyfileobj(open('1.txt'),open('2.txt','w'))
>>> os.system('ls')
1.txt  2.txt
>>> 
View Code 

shutil.copyfile(fsrc,fdes)  复制文件,我们只需要传入文件名称即可进行复制,不用自行预先打开,等于创建一个新的文件,把老文件写入到新文件中然后关闭,新创建的文件权限和属主等信息遵循操作系统规定

>>> shutil.copyfile('1.txt','3.txt')
>>> os.system('ls')
1.txt  2.txt  3.txt
View Code 

shutil.copymode(src,des)  复制文件权限,既把src文件的权限复制给 des文件,只改变权限,不改变其他比如属组,内容等(des文件必须存在)

>>> os.system('ls -l')
total 12
-rwxrwxrwx 1 root root 6 Mar  9 18:35 1.txt
-rw-r--r-- 1 root root 6 Mar  9 18:36 2.txt
-rw-r--r-- 1 root root 6 Mar  9 18:38 3.txt
>>> shutil.copymode('1.txt','2.txt')
>>> os.system('ls -l')
total 12
-rwxrwxrwx 1 root root 6 Mar  9 18:35 1.txt
-rwxrwxrwx 1 root root 6 Mar  9 18:36 2.txt
-rw-r--r-- 1 root root 6 Mar  9 18:38 3.txt
>>> 
View Code

shutil.copystat(src,des)  复制文件的权限,还包括,atime,mtime,flags等信息,不改变文件内容(des需存在)

>>> os.system('stat 1.txt')
  File: `1.txt'
  Size: 6             Blocks: 8          IO Block: 4096   regular file
Device: fd00h/64768d    Inode: 926326      Links: 1
Access: (0777/-rwxrwxrwx)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2017-03-09 18:36:59.223738919 +0800
Modify: 2017-03-09 18:35:23.148738381 +0800
Change: 2017-03-09 18:39:59.061738605 +0800

>>> os.system('stat 3.txt')
  File: `3.txt'
  Size: 6             Blocks: 8          IO Block: 4096   regular file
Device: fd00h/64768d    Inode: 940237      Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2017-03-09 18:39:42.214738376 +0800
Modify: 2017-03-09 18:38:13.862738316 +0800
Change: 2017-03-09 18:38:13.862738316 +0800

>>> shutil.copystat('1.txt','3.txt')
>>> os.system('stat 3.txt')
  File: `3.txt'
  Size: 6             Blocks: 8          IO Block: 4096   regular file
Device: fd00h/64768d    Inode: 940237      Links: 1
Access: (0777/-rwxrwxrwx)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2017-03-09 18:36:59.223738000 +0800
Modify: 2017-03-09 18:35:23.148738000 +0800
Change: 2017-03-09 18:44:33.286738354 +0800
>>> 
View Code

shutil.copy(src,des)  复制文件的同时复制权限信息(等于shutil.copyfile + shutil.copystat)

shutil.copytree(des,src,ignore = shutil.ignore_patterns('*py'))  递归复制文件,类似于copy -r

>>> os.system('ls -l')
total 4
drwxr-xr-x 2 root root 4096 Mar  9 18:46 test

>>> shutil.copytree('test','test1')
>>> os.system('ls -l')
total 8
drwxr-xr-x 2 root root 4096 Mar  9 18:46 test
drwxr-xr-x 2 root root 4096 Mar  9 18:46 test1

>>> os.system('ls -l test1')
total 12
-rwxrwxrwx 1 root root 6 Mar  9 18:35 1.txt
-rwxrwxrwx 1 root root 6 Mar  9 18:36 2.txt
-rwxrwxrwx 1 root root 6 Mar  9 18:35 3.txt
>>> 
View Code

shutil.rmtree(des)  递归的删除文件,类似于 rm -rf

>>> os.system('ls -l')
total 8
drwxr-xr-x 2 root root 4096 Mar  9 18:46 test
drwxr-xr-x 2 root root 4096 Mar  9 18:46 test1

>>> shutil.rmtree('test1')
>>> os.system('ls -l')
total 4
drwxr-xr-x 2 root root 4096 Mar  9 18:46 test
>>> 
View Code

shutil.move(src,des)  移动文件/目录,类似于mv 命令

shutil.make_archive('data_bak','gztar',roots_dir = '/data' )  压缩,data_bak 可以写为绝对路径

import tarfile
t = tarfile.open('data_bak.tar.gz') #打开我呢间
t.extractall('/tmp') #解压缩到某个路径
t.close()

#tar打包
t = tarfile.open('data_bak.tar','w')
t.add(r'/tmp/1.txt') --> #会把程序的路径也进行打包
t.close()

#tar打包
t =tarfile.open('data_bak.tar.gz')
t.add('/tmp/1.txt',arcname='1.txt_bak') # 打包的时候把 /tmp/1.txt 打包成 1.txt_bak
View Code

json&pickle模块

为什么要序列化
  1、持久保存状态
  2、跨平台数据交互
如何序列化:
  1、json(跨平台) 支持字典(dict)、列表(list)、字符串(str)、整型浮点型(int/float)、bool(True,False),null(None)
  2、pickle(纯Python)

eval不能识别非Python语法的数据类型,所以很多时候要用json

json

序列化:

import json
string = json.dumps(obj)   #直接把obj转换成str
with open('a.json','w') as f:
    f.write(string)
View Code

  反序列化:

import json
with open('a.json','r') as f:
    res = f.read()
json.loads(res)      #把str转换成Python识别的数据格式
View Code

  直接序列化到文件中去:

import json
json.dump(obj,文件对象(w方式))
View Code

  直接从文件中反序列化:

import json
json.load(文件对象(r模式)
View Code

PS:Json默认情况下,dumps()方法不知道如何将实例变为一个JSON的{}对象。可选参数default就是把任意一个对象变成一个可序列为JSON的对象,我们只需要为专门写一个转换函数,再把函数传进去即可:

import json

class Student(object):

    def __init__(self,name,age,job):
        self.name = name
        self.age = age
        self.job = job


def converclass(std):

    return {
        'name':std.name,
        'age':std.age,
        'job':std.job
    }

a = Student('daxin',20,'Pythoner')
a_json = json.dumps(a,default=converclass)
print(a_json)

但是如果再来一个Teacher类的话,那么上面的转换方法就不适用了,这里我们可以偷个懒,使用类的__dict__属性

import json

class Student(object):

    def __init__(self,name,age,job):
        self.name = name
        self.age = age
        self.job = job

a = Student('daxin',20,'Pythoner')
a_json = json.dumps(a,default=lambda obj:obj.__dict__)
print(a_json)

同样反序列化的时候,使用object_hook可以定制反序列化的规则

import json

class Student(object):

    def __init__(self,name,age,job):
        self.name = name
        self.age = age
        self.job = job

a = Student('daxin',20,'Pythoner')
a_json = json.dumps(a,default=lambda obj:obj.__dict__)

def restoclass(s):
    return Student(s['name'],s['age'],s['job'])

b = json.loads(a_json,object_hook=restoclass)

pickle

  序列化:需要用b模式打开文件

import pickle
dic = {
'name':'daxin',
'age':18,
'job':'Linux'
}

pic_dumps = pickle.dumps(dic) #序列化存储
with open('a.pickle','wb') as fd:
    fd.write(pic_dumps)
View Code

  反序列化:

import pickle
with open('a.pickle','rb') as fd:
    dic = pickle.loads(fd.read())
View Code

  直接序列化到文件中去:

import pickle
dic = {
'name':'daxin',
'age':18,
'job':'Linux'
}
pickle.dump(dic,open('b.pickle','wb'))
View Code

  直接从文件中反序列化:

import pickle
with open('b.pickle','rb') as fd:
    print(pickle.loads(fd.read()))
View Code

小结

  1、json是通用的格式,如果涉及多个系统之间的交互,选用json
  2、pickle是python特有的,可以序列化一些python独特的数据类型,比如函数
  3、pickle序列化函数的时候,只会序列化函数的内存地址,在脚本执行完毕,那么函数的内存地址就会释放,在其他文件反序列化的时候,那么因为原脚本已经执行完毕,原函数已经释放,所以就会报找不到该函数

shevle模块

  shelve是一个简单的k,v将内存数据通过文件持久化的模块,是对pickle的更高级的封装,可以持久化任何pickle可支持的python数据格式,可以对数据进行多次的dump和load,而不用担心数据混乱。

  注意:它的格式为k,v存储。默认会生成三个文件(.bak/.dat/.dir)

例子:
import shelve

l = [1,2,3,4,5]
d = {'name':'daxin','age':20}
s = {1,2,3,4,5}

#dump
f = shelve.open('shevle')
f['l'] = l
f['d'] = d
f['s'] = s
f.close()

#load
t = shelve.open('shevle')
print(t['l'])
print(t['d'])
print(t['s'])
t.close()
View Code

hashlib模块

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

使用方法1:
 1 hashlib.md5('str').hexdigest() #用MD5对str进行加密,使用hexdigest(),16进制的方式打印 

使用方法2:

1 md5 = hashlib.md5()
2 md5.update('hello')  #如果第一次执行update,那么就是对hello这个字符串进行MD5加密(注意,这里是累加,如果多次update,那么求得是累加的md5值)
3 md5.hexdigest()  #把md5对象保存的str,以16进制进行显示

例子:把文件读入,然后用md5进行校验

import hashlib
import sys

def md5sum(f):
    m = hashlib.md5()
    with open(f) as fd:
        while True:
            data = fd.read(4096)
            if data:
                m.update(data)
            else:
                break
    return m.hexdigest()
if __name__ == '__main__':
   try:
       print md5sum(sys.argv[1]),sys.argv[1]
   except IndexError as e:
       sys.stderr.write('%s want a file\n' %  __file__)

 以上加密算法,可以通过撞库(枚举),去破解,所以我们可以在字符前面加上指定的字符串进行二次加密

>>> import hashlib
>>> m = hashlib.md5('12asvac23as')
>>> m.update('hello')
>>> m.hexdigest()
'cedc722f4b9836fb510c1cc5a4af890c'
>>> 
View Code

subprocess模块

  运行python的时候,我们都是在创建并运行一个进程。像Linux进程那样,一个进程可以fork一个子进程,并让这个子进程exec另外一个程序。在Python中,我们通过标准库中的subprocess包来fork一个子进程,并运行一个外部的程序。
  subprocess包中定义有数个创建子进程的函数,这些函数分别以不同的方式创建子进程,所以我们可以根据需要来从中选取一个使用。另外subprocess还提供了一些管理标准流(standard stream)和管道(pipe)的工具,从而在进程间使用文本通信。

subprocess.call('cmd') 父进程等待子进程完成,返回退出信息(return code,相当于Linux exit code),功能类似于os.system 无法捕获结果。

>>> import subprocess
>>> subprocess.call('w')
19:27:07 up 4 days, 11:55, 5 users, load average: 0.00, 0.00, 0.00
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
root tty1 - Sun07 28:08m 0.03s 0.03s -bash
root pts/2 10.0.0.1 17:13 1:37m 0.13s 0.13s -bash
root pts/3 10.0.0.1 17:18 2:07m 0.01s 0.01s -bash
root pts/4 10.0.0.1 18:01 0.00s 0.10s 0.07s python
root pts/5 10.0.0.1 18:39 40:55 0.08s 0.08s -bash
>>> 
View Code

注意:
  subprocess.call('ls -l')
  注意当执行的cmd中有空格的时候,python解释器会认为后面的是文件,就会报错,那么就需要添加参数shell = True,标识使用shell的方式执行
  或者使用列表 subprocess.call(['ls','-l'])
  subprocess.call('ps axu | grep python',shell=True) 这样就可以

subprocess.check_call('cmd') 功能和call相同,无法捕捉结果。与call不同的是,check_call默认会检查命令的返回值,如果不是0,则会返回subprocess.CalledProcessError异常,

>>> subprocess.check_call(['rm' ,'-rf' ,'/etc/hosts'])
rm: cannot remove `/etc/hosts': Permission denied
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib64/python2.6/subprocess.py", line 505, in check_call
raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['rm', '-rf', '/etc/hosts']' returned non-zero exit status 1
>>>
View Code

  try抓取subprocess.CalledProcessError异常,然后处理

[redis@linux-node1 ~]$ cat sub.py 
#!/usr/bin/env python

import subprocess

try:
subprocess.check_call(['rm','-rf','/etc/hosts'])
except subprocess.CalledProcessError as e:
print('hello world')
[redis@linux-node1 ~]$ 
[redis@linux-node1 ~]$ python3 sub.py 
rm: cannot remove `/etc/hosts': Permission denied
hello world
View Code

subprocess.Popen() 调用外部命令的时候,也会像C那样fork一个子进程进行执行
  通用语法1:subprocess.Popen('cmd',shell=True,stdout=subprocess.PIPE)
  通用语法2:subprocess.Popen(['cmd'],stdout=subprocess.PIPE) -->一般用这种
  上面两行代码功能相同,不写stdout的话,默认会把输出打印到当前的屏幕上
  PIPE 表示管道符,会把命令的输出方式暂时缓存,然后通过对应的方式进行读取
  p.stdout.read() 从管道符中读取命令执行结果
    stdout 表示标准输出
    stdin 表示标准输入
    stdin=subprocess.PIPE,表示输入从PIPE读取
    stderr 表示错误输出
  Popen对象的方法:
    p.pid 查看子进程的PID
    p.poll() 查看执行状态,完毕返回0
    p.returncode 获取进程的返回值
    p.kill() kill掉相关进程
    p.terminate() 暂停进程
    p.wait() 等待进程执行完毕
    p.communicate() 可以和子进程进行交互,可以给子进程的stdin传递参数(子进程的stdin为PIPE),会返回一个元组,(stdout,stderr),需要子进程也输出到PIPE,这样才能接收到 ,所以它会等待子进程执行完毕,相当于p.stdin.write()、p.stdin.close(),p.stdout.read()三个方法
  例子:

 p = Popen(['ls'],stdout=PIPE,stderr=PIPE) ; stdout,stderr = p.communicate() 获取p的stdout和stderr  

注意:
  Popen会fork一个子进程去执行命令,父脚本会继续向下执行,如果要等待Popen执行完毕,那么就需要使用p.wait()来等待子进程执行完毕,再继续执行

PIPE 管道会把命令的结果进行储存
例子:

p1 = Popen(['ls'],stdout = PIPE)
p2 = Popen(['grep','py'],stdin=p1.stdout,stdout=PIPE)
p2.stdout.read()

log模块

  主要用于输出日志信息的模块,其根据日志的级别分为六部分:NOTSET < DEBUG < INFO < WARNING < ERROR < CRITICAL,只有大于当前日志等级的操作才会被记录。

例子:直接输出日志到屏幕上

1 import logging
2 
3 logging.warning('user [root] attempted wrong password more than 3 times')
4 logging.critical('Mysql Service is gone down')

如果想把日志输出到文件中去

1 import logging
2 logging.basicConfig(filename='access.log',level=logging.INFO) #这里可以使用日志级别对应的数字进行指定
3 logging.info('hello info')
4 logging.warning('hello warning')
5 logging.error('hello error')

指定日志格式

1 import logging
2 
3 logging.basicConfig(filename='access.log', level=logging.INFO,
4   format = '%(asctime)s - %(name)s - %(levelname)s - %(module)s: %(message)s',
5   datefmt = '%Y-%m-%d %X')
6 logging.info('hello info')
7 logging.warning('hello warning')

logging.basicConfig函数各参数:
  filename: 指定日志文件名
  filemode: 和file函数意义相同,指定日志文件的打开模式,'w'或'a'
  datefmt: 指定时间格式,同time.strftime()
  level: 设置日志级别,默认为logging.WARNING
  stream: 指定将日志的输出流,可以指定输出到sys.stderr,sys.stdout或者文件,默认输出到sys.stderr,当stream和filename同时指定时,stream被忽略
  format: 指定输出的格式和内容,format可以输出很多有用信息,如上例所示:

%(name)s Logger的名字
%(levelno)s 数字形式的日志级别()
%(levelname)s 文本形式的日志级别
%(pathname)s 调用日志输出函数的模块的完整路径名,可能没有
%(filename)s 调用日志输出函数的模块的文件名
%(module)s 调用日志输出函数的模块名
%(funcName)s 调用日志输出函数的函数名
%(lineno)d 调用日志输出函数的语句所在的代码行
%(created)f 当前时间,用UNIX标准的表示时间的浮 点数表示
%(relativeCreated)d 输出日志信息时的,自Logger创建以 来的毫秒数
%(asctime)s 字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒
%(thread)d 线程ID。可能没有
%(threadName)s 线程名。可能没有
%(process)d 进程ID。可能没有
%(message)s 用户输出的消息
View Code

日志等级(数字表达形式):

CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0
View Code

confingparser模块

  用于生成和修改常见配置文档,比如:MySQL
  在2.x里,模块名为ConfigParser,在3.x里为configparser
  在configparser的参数通过字典进行定义

例子:利用configparser编写一个配置文件

 1 import configparser
 2 
 3 config = configparser.ConfigParser() # 实例化一个配置对象
 4 #定义方法1:直接利用key:value定义
 5 config['Default'] = {'name':'daxin','age':20,'job':'Linux'}
 6 
 7 #定义方法2:
 8 config['Global'] = {}
 9 config['Global']['name'] = 'daxin'
10 config['Global']['age'] = '20'
11 config['Global']['job'] = 'Linux'
12 
13 #定义方法3:
14 config['localhost'] = {}
15 localconfig = config['localhost']
16 localconfig['name'] = 'daxin'
17 localconfig['age'] = '20'
18 localconfig['job'] = 'Linux'
19 
20 #写入配置文件
21 with open('example.ini','w') as fd:
22 config.write(fd) #这里的确是通过实例化的对象的write,写入一个打开的文件中去

读取配置文件内容:

1 # Author:Lee Sir
2 
3 import configparser
4 conf = configparser.ConfigParser() #创建一个configparser对象
5 conf.read('example.ini') #读取配置文件
6 for node in conf.sections(): #sections表示列出配置文件中配置段的title
7     print(node)
8     for item in conf[node]:
9         print(item,conf[node][item])

XML模块

  xml可扩展标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。
  功能是实现不同语言或程序之前进行数据交换的协议,跟json差不多,但json使用起来更简单,不过,古时候,json还没有诞生的黑暗年代,大家只能选择用xml进行数据交换,所以很多老系统的接口还是xml

  xml的格式,主要通过<>节点来区别数据结构的

示例数据:

 1 <?xml version="1.0"?>
 2 <data>
 3     <country name="Liechtenstein">
 4         <rank updated="yes">2</rank>      -->    rank为开头   /rank为结尾
 5         <year>2008</year>
 6         <gdppc>141100</gdppc>
 7         <neighbor name="Austria" direction="E"/>
 8         <neighbor name="Switzerland" direction="W"/>
 9     </country>
10     <country name="Singapore">
11         <rank updated="yes">5</rank>
12         <year>2011</year>
13         <gdppc>59900</gdppc>
14         <neighbor name="Malaysia" direction="N"/>
15     </country>
16     <country name="Panama">
17         <rank updated="yes">69</rank>
18         <year>2011</year>
19         <gdppc>13600</gdppc>
20         <neighbor name="Costa Rica" direction="W"/>       neighbor/自结束标签,可以在/之前添加参数等
21         <neighbor name="Colombia" direction="E"/>
22     </country>
23 </data>

利用python处理xml数据
  python有三种方法来解析xml,SAX、DOM、以及ElementTree
  因为elementTree更轻量级,所以这里用ElementTree进行学习

例子:

# Author:Lee Sir
import xml.etree.ElementTree as ET #引入ElementTree模块对xml进行处理

tree = ET.parse("xmltest.xml") #ElementTree.parse(source,parser=None) 将xml文件进行加载,并返回ElementTree对象,parser表示使用什么解析器,默认使用标准的xml解析器

root = tree.getroot() #得到根节点,返回根节点的element对象(既最外层的tag名称),这里也可以使用find,查找匹配到的第一个tag,tree.find('data'),并返回以该tag为起始的根结点树状结构

print(root.tag) #打印最外层的tag的名称

# 遍历xml文档
for child in root: #遍历根节点
    print(child.tag, child.attrib) #打印根节点下的tag的名称和属性
    for i in child: #如果有嵌套tag,那么打印tag的名称是对应的值
       print(i.tag, i.text)

# 只遍历year 节点
for node in root.iter('year'): #root.iter对所有tag节点进行过滤year
    print(node.tag, node.text) #打印对应的tag名称和值

 

增删改查:
http://www.tuicool.com/articles/fmMz2m

转载于:https://www.cnblogs.com/dachenzi/articles/6945766.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值