编辑推荐: |
来源于csdn,共讲解了16个模块,分别代码详细描述,希望对大家工作有帮助。 |
|
1、time & datetime模块
时间相关的操作,时间有三种表示方式:
时间戳 1970年1月1日之后的秒,即:time.time()
格式化的字符串 2014-11-11 11:11, 即:time.strftime('%Y-%m-%d')
结构化时间 元组包含了:年、日、星期等...time.struct_time 即:time.localtime()
print(time.time())
print(time.mktime(time.localtime()))
print(time.gmtime()) #可加时间戳参数
print(time.localtime()) #可加时间戳参数
print(time.strptime('2014-11-11', '%Y-%m-%d'))
print(time.strftime('%Y-%m-%d %X')) #默认当前时间
print(time.strftime('%Y-%m-%d %X',time.localtime()))
#默认当前时间
print(time.asctime())
print(time.asctime(time.localtime()))
print(time.ctime(time.time())) #ctime后面加的是时间戳
import datetime
"""
datetime.date:表示日期的类。常用的属性有year, month, day
datetime.time:表示时间的类。常用的属性有hour, minute, second,
microsecond
datetime.datetime:表示日期时间
datetime.timedelta:表示时间间隔,即两个时间点之间的长度
timedelta([days[, seconds[, microseconds[, milliseconds[,
minutes[, hours[, weeks]]]]]]])
strftime("%Y-%m-%d")
"""
import datetime
print(datetime.datetime.now())
print(datetime.datetime.now() - datetime.timedelta(days=5)) |
2、random模块
#随机数
import random
print(random.random())
print(random.randint(1,8)) #包括8
print(random.randrange(1,10)) #不包括10
print(random.choice([1,2,3,4]))
print(random.sample([1,2,3,4],1)) #后面的1表示从序列中取几个值
#生成随机验证码
import random
checkcode = ''
for i in range(4):
current = random.randrange(0,4)
if current != i:
temp = chr(random.randint(65,90)) #65-90通过转换为大写字母,97-122通过转换为小写字母
else:
temp = random.randint(0,9)
checkcode += str(temp)
print(checkcode) |
3、OS模块
提供对操作系统进行调用的接口
os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径
os.chdir("dirname") 改变当前脚本工作目录;相当于shell下cd
os.curdir 返回当前目录: ('.')
os.pardir 获取当前目录的父目录字符串名:('..')
os.makedirs('dirname1/dirname2') 可生成多层递归目录
os.removedirs('dirname1') 若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推
os.mkdir('dirname') 生成单级目录;相当于shell中mkdir dirname
os.rmdir('dirname') 删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir
dirname
os.listdir('dirname') 列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
os.remove() 删除一个文件
os.rename("oldname","newname")
重命名文件/目录
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所指向的文件或者目录的最后修改时间
os.popen(path) 例如:运行a = os.popen('dir').read()
print(a),可以显示dir下的所有内容 |
4、sys模块
sys.argv 命令行参数List,第一个元素是程序本身路径
sys.exit(n) 退出程序,正常退出时exit(0)
sys.version 获取Python解释程序的版本信息
sys.maxint 最大的Int值
sys.path 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
sys.platform 返回操作系统平台名称
sys.stdout.write('please:')
val = sys.stdin.readline()[:-1] |
5、shutil模块
高级的 文件、文件夹、压缩包 处理模块
shutil.copyfileobj(fsrc,
fdst[, length]) 将文件内容(或者叫文件对象)拷贝到另一个文件中,可以部分内容
shutil.copyfile(src, dst) 拷贝文件
shutil.copymode(src, dst) 仅拷贝权限。内容、组、用户均不变
shutil.copystat(src, dst) 拷贝状态的信息,包括:mode bits,
atime, mtime, flags
shutil.copy(src, dst) 拷贝文件和权限
shutil.copy2(src, dst) 拷贝文件和状态信息
shutil.ignore_patterns(*patterns)
shutil.copytree(src, dst, symlinks=False, ignore=None)
递归的去拷贝文件
例如:copytree(source, destination, ignore=ignore_patterns('*.pyc',
'tmp*'))
shutil.rmtree(path[, ignore_errors[, onerror]])
递归的去删除文件
shutil.move(src, dst) 递归的去移动文件
shutil.make_archive(base_name, format,...)
创建压缩包并返回文件路径,例如:zip、tar
base_name:压缩包的文件名,也可以是压缩包的路径。只是文件名时,则保存至当前目录,否则保存至指定路径,如:backup=>保存至当前路径;如:/home/www/backup
=>保存至/home/www/
format:压缩包种类,“zip”, “tar”, “bztar”,“gztar”
root_dir:要压缩的文件夹路径(默认当前目录)
owner:用户,默认当前用户
group:组,默认当前组
logger:用于记录日志,通常是logging.Logger对象 |
#将 /home/www/Downloads/test
下的文件打包放置当前程序目录
import shutil
ret = shutil.make_archive("test", 'gztar',
root_dir='/home/www/Downloads/test')
```
#将/home/www/Downloads/test 下的文件打包放置 /home/www/目录
import shutil
ret = shutil.make_archive("/home/www/test",
'gztar', root_dir='/home/www/Downloads/test') |
shutil 对压缩包的处理是调用 ZipFile 和 TarFile 两个模块来进行的,详细
zipfile 压缩解压
import zipfile
# 压缩
z = zipfile.ZipFile('test.zip', 'w')
z.write('a.log')
z.write('data.data')
z.close()
# 解压
z = zipfile.ZipFile('test.zip', 'r')
z.extractall()
z.close() |
tarfile 压缩解压
import tarfile
# 压缩
tar = tarfile.open('test.tar','w')
tar.add('/home/www/bbs2.zip', arcname='bbs2.zip')
tar.add('/home/www/cmdb.zip', arcname='cmdb.zip')
tar.close()
# 解压
tar = tarfile.open(test.tar','r')
tar.extractall() # 可设置解压地址
tar.close() |
备注:
1、shutil.copymode(src, dst) 的源代码
def copymode(src,
dst): """Copy mode bits from
src to dst"""
if hasattr(os, 'chmod'):
st = os.stat(src)
mode = stat.S_IMODE(st.st_mode)
os.chmod(dst, mode) |
6、json & pickle 模块
用于序列化的两个模块
json,用于字符串 和 python数据类型间进行转换
pickle,用于python特有的类型 和 python的数据类型间进行转换
json模块提供了四个功能:dumps、dump、loads、load
pickle模块提供了四个功能:dumps、dump、loads、load
import pickle
data = {'k1':123,'k2':'hello'}
#pickle.dumps 将数据通过特殊的形式转换为只有python语言识别的字符串
p_str = pickle.dumps(data)
print(p_str)
#pickle.dump 将数据通过特殊的形式转换为只有python语言识别的字符串,并写入文件
with open('D:/result.pk','w') as fp:
pickle.dump(data,fp)
import json
#json.dumps 将数据通过特殊的形式转换为所有程序语言识别的字符串
j_str = json.dumps(data)
print(j_str)
#json.dump 将数据通过特殊的形式转换为所有程序语言识别的字符串,并写入文件
with open('D:/result.json','w') as fp:
json.dump(data,fp) |
7、shelve 模块
shelve模块是一个简单的k,v将内存数据通过文件持久化的模块,可以持久化任何pickle可支持的python数据格式
import shelve
d = shelve.open('shelve_test') #打开一个文件
class Test(object):
def __init__(self,n):
self.n = n
t = Test(123)
t2 = Test(123334)
name = ["alex","rain","test"]
d["test"] = name #持久化列表
d["t1"] = t #持久化类
d["t2"] = t2
d.close() |
8、xml处理模块
xml是实现不同语言或程序之间进行数据交换的协议,跟json差不多,但json使用起来更简单,不过,在json还没诞生的黑暗年代,大家只能选择用xml呀,至今很多传统公司如金融行业的很多系统的接口还主要是xml。
xml的格式如下,就是通过<>节点来区别数据结构的:
<?xml version="1.0"?>
<data> <country name="Liechtenstein">
<rank updated="yes">2</rank>
<year>2008</year> <gdppc>141100</gdppc>
<neighbor name="Austria" direction="E"/>
<neighbor name="Switzerland" direction="W"/>
</country> <country name="Singapore">
<rank updated="yes">5</rank>
<year>2011</year> <gdppc>59900</gdppc>
<neighbor name="Malaysia" direction="N"/>
</country> <country name="Panama">
<rank updated="yes">69</rank>
<year>2011</year> <gdppc>13600</gdppc>
<neighbor name="Costa Rica" direction="W"/>
<neighbor name="Colombia" direction="E"/>
</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
XML格式类型是节点嵌套节点,对于每一个节点均有以下功能,以便对当前节点进行操作
由于 每个节点 都具有以上的方法,并且在上一步骤中解析时均得到了root(xml文件的根节点),可以利用以上方法进行操作xml文件。
a、遍历XML文档的所有内容
from xml.etree
import ElementTree as ET
############ 解析方式一 ############
# 打开文件,读取XML内容
str_xml = open('xo.xml', 'r').read()
# 将字符串解析成xml特殊对象,root代指xml文件的根节点
root = ET.XML(str_xml)
############ 解析方式二 ############
# 直接解析xml文件
#tree = ET.parse("xo.xml")
# 获取xml文件的根节点
#root = tree.getroot()
### 操作
# 顶层标签print(root.tag)
# 遍历XML文档的第二层for child in root:
# 第二层节点的标签名称和标签属性
print(child.tag, child.attrib)
# 遍历XML文档的第三层
for i in child:
# 第二层节点的标签名称和内容
print(i.tag,i.text) |
b、遍历XML中指定的节点
from xml.etree
import ElementTree as ET
############ 解析方式一 ############
# 打开文件,读取XML内容
#str_xml = open('xo.xml', 'r').read()
# 将字符串解析成xml特殊对象,root代指xml文件的根节点
#root = ET.XML(str_xml)
############ 解析方式二 ############
# 直接解析xml文件
tree = ET.parse("xo.xml")
# 获取xml文件的根节点
root = tree.getroot()
### 操作
# 顶层标签 print(root.tag)
# 遍历XML中所有的year节点for node in root.iter('year'):
# 节点的标签名称和内容
print(node.tag, node.text) |
c、修改节点内容
由于修改的节点时,均是在内存中进行,其不会影响文件中的内容。所以,如果想要修改,则需要重新将内存中的内容写到文件。
①解析字符串方式,修改,保存
from xml.etree
import ElementTree as ET
############ 解析方式一 ############
# 打开文件,读取XML内容
str_xml = open('xo.xml', 'r').read()
# 将字符串解析成xml特殊对象,root代指xml文件的根节点
root = ET.XML(str_xml)
############ 操作 ############
# 顶层标签print(root.tag)
# 循环所有的year节点for node in root.iter('year'):
# 将year节点中的内容自增一
new_year = int(node.text) + 1
node.text = str(new_year)
# 设置属性
node.set('name', 'alex')
node.set('age', '18')
# 删除属性
del node.attrib['name']
############ 保存文件 ############
tree = ET.ElementTree(root)
tree.write("newnew.xml", encoding='utf-8') |
②解析文件方式,修改,保存
from xml.etree
import ElementTree as ET
############ 解析方式二 ############
# 直接解析xml文件
tree = ET.parse("xo.xml")
# 获取xml文件的根节点
root = tree.getroot()
############ 操作 ############
# 顶层标签print(root.tag)
# 循环所有的year节点for node in root.iter('year'):
# 将year节点中的内容自增一
new_year = int(node.text) + 1
node.text = str(new_year)
# 设置属性
node.set('name', 'alex')
node.set('age', '18')
# 删除属性
del node.attrib['name']
############ 保存文件 ############
tree.write("newnew.xml", encoding='utf-8') |
d、删除节点
①解析字符串方式打开,删除,保存
from xml.etree
import ElementTree as ET
############ 解析字符串方式打开 ############
# 打开文件,读取XML内容
str_xml = open('xo.xml', 'r').read()
# 将字符串解析成xml特殊对象,root代指xml文件的根节点
root = ET.XML(str_xml)
############ 操作 ############
# 顶层标签print(root.tag)
# 遍历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("newnew.xml", encoding='utf-8') |
②解析文件方式打开,删除,保存
from xml.etree
import ElementTree as ET
############ 解析文件方式 ############
# 直接解析xml文件
tree = ET.parse("xo.xml")
# 获取xml文件的根节点
root = tree.getroot()
############ 操作 ############
# 顶层标签print(root.tag)
# 遍历data下的所有country节点for country in root.findall('country'):
# 获取每一个country节点下rank节点的内容
rank = int(country.find('rank').text)
if rank > 50:
# 删除指定country节点 root.remove(country)
############ 保存文件 ############
tree.write("newnew.xml", encoding='utf-8') |
(3)创建XML文档
a、方式(一)
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('oooo.xml',encoding='utf-8', short_empty_elements=False) |
b、创建方式(二)
from xml.etree
import ElementTree as ET
# 创建根节点
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)
tree = ET.ElementTree(root)
tree.write('oooo.xml',encoding='utf-8', short_empty_elements=False) |
c、创建方式(三)
from xml.etree
import ElementTree as ET
# 创建根节点
root = ET.Element("famliy")
# 创建节点大儿子
son1 = ET.SubElement(root, "son", attrib={'name':
'儿1'})# 创建小儿子
son2 = ET.SubElement(root, "son", attrib={"name":
"儿2"})
# 在大儿子中创建一个孙子
grandson1 = ET.SubElement(son1, "age",
attrib={'name': '儿11'})
grandson1.text = '孙子'
et = ET.ElementTree(root) #生成文档对象
et.write("test.xml", encoding="utf-8",
xml_declaration=True, short_empty_elements=False) |
d、由于原生保存的XML时默认无缩进,如果想要设置缩进的话, 需要修改保存方式:
from xml.etree
import ElementTree as ETfrom 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("xxxoo.xml",'w',encoding='utf-8')
f.write(raw_str)
f.close() |
(4)命名空间
from xml.etree
import ElementTree as ET
ET.register_namespace('com',"http://www.company.com")
#some name
# build a tree structure
root = ET.Element("{http://www.company.com}STUFF")
body = ET.SubElement(root, "{http://www.company.com}MORE_STUFF",
attrib={"{http://www.company.com}hhh":
"123"})
body.text = "STUFF EVERYWHERE!"
# wrap it in an ElementTree instance, and save
as XML
tree = ET.ElementTree(root)
tree.write("page.xml",
xml_declaration=True,
encoding='utf-8',
method="xml") |
(5)比较清楚的操作
import xml.etree.ElementTree
as ET
tree = ET.parse("xmltest.xml")
root = tree.getroot()
print(root.tag)
#遍历xml文档
for child in root:
print(child.tag, child.attrib)
for i in child:
print(i.tag,i.text)
#只遍历year 节点
for node in root.iter('year'):
print(node.tag,node.text)
#修改和删除xml文档内容
import xml.etree.ElementTree as ET
tree = ET.parse("xmltest.xml")
root = tree.getroot()
#修改
for node in root.iter('year'):
new_year = int(node.text) + 1
node.text = str(new_year)
node.set("updated","yes")
tree.write("xmltest.xml")
#删除node
for country in root.findall('country'):
rank = int(country.find('rank').text)
if rank > 50:
root.remove(country)
tree.write('output.xml')
#自己创建xml文档
import xml.etree.ElementTree as ET
new_xml = ET.Element("namelist")
name = ET.SubElement(new_xml,"name",attrib={"enrolled":"yes"})
age = ET.SubElement(name,"age",attrib={"checked":"no"})
sex = ET.SubElement(name,"sex")
sex.text = '33'
name2 = ET.SubElement(new_xml,"name",attrib={"enrolled":"no"})
age = ET.SubElement(name2,"age")
age.text = '19'
et = ET.ElementTree(new_xml) #生成文档对象
et.write("test.xml", encoding="utf-8",xml_declaration=True)
ET.dump(new_xml) #打印生成的格式
|
9、PyYAML模块
Python也可以很容易的处理ymal文档格式,只不过需要安装一个模块,参考文档:http://pyyaml.org/wiki/PyYAMLDocumentation
10、configparser模块
用于生成和修改常见配置文档,当前模块的名称在 python 2.x 版本中为 ConfigParser。来看一个好多软件的常见文档格式如下
[DEFAULT]
ServerAliveInterval = 45
Compression = yes
CompressionLevel = 9
ForwardX11 = yes
[bitbucket.org]
User = hg
[topsecret.server.com]
Port = 50022
ForwardX11 = no |
如果想用python生成一个这样的文档怎么做呢
import configparser
config = configparser.ConfigParser()
config["DEFAULT"] = {'ServerAliveInterval':
'45',
'Compression': 'yes',
'CompressionLevel': '9'}
config['bitbucket.org'] = {}
config['bitbucket.org']['User'] = 'hg'
config['topsecret.server.com'] = {}
topsecret = config['topsecret.server.com']
topsecret['Host Port'] = '50022' # mutates the
parser
topsecret['ForwardX11'] = 'no' # same here
config['DEFAULT']['ForwardX11'] = 'yes'
with open('example.ini', 'w') as configfile:
config.write(configfile) |
写完了还可以再读出来
>>> import
configparser
>>> config = configparser.ConfigParser()
>>> config.sections()
[]
>>> config.read('example.ini')
['example.ini']
>>> config.sections()
['bitbucket.org', 'topsecret.server.com']
>>> 'bitbucket.org' in config
True
>>> 'bytebong.com' in config
False
>>> config['bitbucket.org']['User']
'hg'
>>> config['DEFAULT']['Compression']
'yes'
>>> topsecret = config['topsecret.server.com']
>>> topsecret['ForwardX11']
'no'
>>> topsecret['Port']
'50022'
>>> for key in config['bitbucket.org']:
print(key)
...
user
compressionlevel
serveraliveinterval
compression
forwardx11
>>> config['bitbucket.org']['ForwardX11']
'yes' |
configparser增删改查语法
[section1]
k1 = v1
k2:v2
[section2]
k1 = v1
import ConfigParser
config = ConfigParser.ConfigParser()
config.read('i.cfg')
# ########## 读 ##########
#secs = config.sections()
#print secs
#options = config.options('group2')
#print options
#item_list = config.items('group2')
#print item_list
#val = config.get('group1','key')
#val = config.getint('group1','key')
# ########## 改写 ##########
#sec = config.remove_section('group1')
#config.write(open('i.cfg', "w"))
#sec = config.has_section('wupeiqi')
#sec = config.add_section('wupeiqi')
#config.write(open('i.cfg', "w"))
#config.set('group2','k1',11111)
#config.write(open('i.cfg', "w"))
#config.remove_option('group2','age')
#config.write(open('i.cfg', "w")) |
11、hashlib模块
用于加密相关的操作,代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256,
SHA384, SHA512 ,MD5 算法
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()) |
以上加密算法虽然依然非常厉害,但时候存在缺陷,即:通过撞库可以反解。所以,有必要对加密算法中添加自定义key再来做加密。
import hashlib
# ######## md5 ########
hash = hashlib.md5('898oaFs09f')
hash.update('admin')
print(hash.hexdigest()) |
还不够吊?python 还有一个 hmac 模块,它内部对我们创建 key 和 内容 再进行处理然后再加密
import hmac
h = hmac.new('wueiqi')
h.update('hellowo')
print(hash.hexdigest()) |
备注:在python3中,加密字符串需要将字符串转换为bytes类型,转换方法
hash.update(b'admin')
或者 hash.update('admin'.encode('utf8')) |
12、logging模块
很多程序都有记录日志的需求,并且日志中包含的信息即有正常的程序访问日志,还可能有错误、警告等信息输出,python的logging模块提供了标准的日志接口,你可以通过它存储各种格式的日志,logging的日志可以分为
debug(), info(), warning(), error() and critical()
5个级别,下面我们看一下怎么用。
①最简单用法
import logging
logging.warning("user [tom] attempted wrong
password more than 3 times")
logging.critical("server is down")
#输出
WARNING:root:user [tom] attempted wrong password
more than 3 times
CRITICAL:root:server is down |
②如果想把日志写到文件里
import logging
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s %(filename)s[line:%(lineno)d]
%(levelname)s %(message)s',
datefmt='%a, %d %b %Y %H:%M:%S',
filename='test.log',
filemode='a')
logging.debug('This message should go to the
log file')
logging.info('So should this')
logging.warning('And this, too') |
其中下面这句中的level=loggin.INFO意思是,把日志纪录级别设置为INFO,也就是说,只有比日志是INFO或比INFO级别更高的日志才会被纪录到文件里,在这个例子,
第一条日志是不会被纪录的,如果希望纪录debug的日志,那把日志级别改成DEBUG就行了。
logging.basicConfig (filename='example.log', level=logging.INFO) |
对于格式,有如下属性可是配置:
logging.basicConfig函数各参数:
filename: 指定日志文件名
filemode: 和file函数意义相同,指定日志文件的打开模式,'w'或'a'
format: 指定输出的格式和内容,format可以输出很多有用信息,如上例所示:
%(levelno)s: 打印日志级别的数值
%(levelname)s: 打印日志级别名称
%(pathname)s: 打印当前执行程序的路径,其实就是sys.argv[0]
%(filename)s: 打印当前执行程序名
%(funcName)s: 打印日志的当前函数
%(lineno)d: 打印日志的当前行号
%(asctime)s: 打印日志的时间
%(thread)d: 打印线程ID
%(threadName)s: 打印线程名称
%(process)d: 打印进程ID
%(message)s: 打印日志信息
datefmt: 指定时间格式,同time.strftime()
level: 设置日志级别,默认为logging.WARNING
stream: 指定将日志的输出流,可以指定输出到sys.stderr,sys.stdout或者文件,默认输出到sys.stderr,当stream和filename同时指定时,stream被忽略 |
③将日志同时输出到文件和屏幕(比较灵活的方式)
import logging
logger = logging.getLogger() #创建一个logger对象
fileoutput = logging.FileHandler('test.log') #创建一个handler,用于输出到文件
screenoutput = logging.StreamHandler() #创建一个handler,用于输出到控制台
fmt = logging.Formatter(
'%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s
%(message)s'
) #输出格式
fileoutput.setFormatter(fmt)
screenoutput.setFormatter(fmt)
logger.addHandler(fileoutput)
logger.addHandler(screenoutput)
logger.setLevel(logging.DEBUG) #设置日志的级别
logging.debug('This message should go to the
log file')
logging.info('So should this')
logging.warning('And this, too')
屏幕上打印:
2017-5-12 10:35:48 bbb.py[line:21] DEBUG This
message should go to the log file
2017-5-12 10:35:48 bbb.py[line:22] INFO So should
this
2017-5-12 10:35:48 bbb.py[line:23] WARNING And
this, too
test.log文件中内容为:
2017-5-12 10:35:48 bbb.py[line:21] DEBUG This
message should go to the log file
2017-5-12 10:35:48 bbb.py[line:22] INFO So should
this
2017-5-12 10:35:48 bbb.py[line:23] WARNING And
this, too |
④logging之日志回滚
import logging
from logging.handlers import RotatingFileHandler
#定义一个RotatingFileHandler,最多备份5个日志文件,每个日志文件最大10M
Rthandler = RotatingFileHandler('myapp.log', maxBytes=10*1024*1024,backupCount=5)
Rthandler.setLevel(logging.INFO)
formatter = logging.Formatter('%(name)-12s: %(levelname)-8s
%(message)s')
Rthandler.setFormatter(formatter)
logging.getLogger('').addHandler(Rthandler)
|
从上例和本例可以看出,logging有一个日志处理的主对象,其它处理方式都是通过addHandler添加进去的。
logging的几种handle方式如下:
logging.StreamHandler:
日志输出到流,可以是sys.stderr、sys.stdout或者文件
logging.FileHandler: 日志输出到文件
日志回滚方式,实际使用时用RotatingFileHandler和TimedRotatingFileHandler
logging.handlers.BaseRotatingHandler
logging.handlers.RotatingFileHandler
logging.handlers.TimedRotatingFileHandler
logging.handlers.SocketHandler: 远程输出日志到TCP/IP
sockets
logging.handlers.DatagramHandler: 远程输出日志到UDP sockets
logging.handlers.SMTPHandler: 远程输出日志到邮件地址
logging.handlers.SysLogHandler: 日志输出到syslog
logging.handlers.NTEventLogHandler: 远程输出日志到Windows
NT/2000/XP的事件日志
logging.handlers.MemoryHandler: 日志输出到内存中的制定buffer
logging.handlers.HTTPHandler: 通过"GET"或"POST"远程输出到HTTP服务器 |
⑤通过logging.config模块配置日志
#logger.conf
###############################################
[loggers]
keys=root,example01,example02
[logger_root]
level=DEBUG
handlers=hand01,hand02
[logger_example01]
handlers=hand01,hand02
qualname=example01
propagate=0
[logger_example02]
handlers=hand01,hand03
qualname=example02
propagate=0
###############################################
[handlers]
keys=hand01,hand02,hand03
[handler_hand01]
class=StreamHandler
level=INFO
formatter=form02
args=(sys.stderr,)
[handler_hand02]
class=FileHandler
level=DEBUG
formatter=form01
args=('myapp.log', 'a')
[handler_hand03]
class=handlers.RotatingFileHandler
level=INFO
formatter=form02
args=('myapp.log', 'a', 10*1024*1024, 5)
###############################################
[formatters]
keys=form01,form02
[formatter_form01]
format=%(asctime)s %(filename)s[line:%(lineno)d]
%(levelname)s %(message)s
datefmt=%a, %d %b %Y %H:%M:%S
[formatter_form02]
format=%(name)-12s: %(levelname)-8s %(message)s
datefmt= |
import logging
import logging.config
logging.config.fileConfig("logger.conf")
logger = logging.getLogger("example01")
logger.debug('This is debug message')
logger.info('This is info message')
logger.warning('This is warning message') |
对于等级:
CRITICAL = 50
FATAL = CRITICAL
ERROR = 40
WARNING = 30
WARN = WARNING
INFO = 20
DEBUG = 10
NOTSET = 0 |
13、re模块
常用正则表达式符号
'.' 默认匹配除\n之外的任意一个字符,若指定flag
DOTALL,则匹配任意字符,包括换行
'^' 匹配字符开头,若指定flags MULTILINE,这种也可以匹配上(r"^a","\nabc\neee",flags=re.MULTILINE)
'$' 匹配字符结尾,或e.search("foo$","bfoo\nsdfsf",flags=re.MULTILINE).group()也可以
'*' 匹配*号前的字符0次或多次(包括0次),re.findall("ab*","cabb3abcbbac")
结果为['abb', 'ab', 'a'] #如果b为0次也可以匹配到
'+' 匹配前一个字符1次或多次(最少1次),re.findall("ab+","ab+cd+abb+bba")
结果['ab', 'abb']
'?' 匹配前一个字符0次或1次
'{m}' 匹配前一个字符m次
'{n,m}' 匹配前一个字符n到m次,re.findall("ab{1,3}","abb
abc abbcbbb") 结果'abb', 'ab', 'abb']
'|' 匹配|左或|右的字符,re.search("abc|ABC","ABCBabcCD").group()
结果'ABC'
'(...)' 分组匹配,re.search("(abc){2}a(123|456)c",
"abcabca456c").group() 结果 abcabca456c
'\A' 只从字符开头匹配,re.search("\Aabc","alexabc")
是匹配不到的
'\Z' 匹配字符结尾,同$
'\d' 匹配数字0-9
'\D' 匹配非数字
'\w' 匹配[A-Za-z0-9]
'\W' 匹配非[A-Za-z0-9]
'\s' 匹配空白字符、\t、\n、\r , re.search("\s+","ab\tc1\n3").group()
结果 '\t'
'(?P<name>...)' 分组匹配 re.search("(?P<province>[0-9]{4})(?P<city>[0-9]{2})(?P<birthday>[0-9]{4})","371481199306143242").groupdict("city")
结果{'province': '3714', 'city': '81', 'birthday':
'1993'} |
#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}$
import re
ret = re.search('(?P<id>\d{3})/(?P<name>\w{3})','negbhgao123/gna')
print(ret.group())
print(ret.group('id'))
print(ret.group('name')) |
最常用的匹配语法
re.match 从头开始匹配
re.search 包含匹配
re.findall 把所有匹配到的字符放到以列表中的元素返回
re.splitall 以匹配到的字符当做列表分隔符
re.sub 匹配字符并替换 |
反斜杠的困扰
与大多数编程语言相同,正则表达式里使用"\"作为转义字符,这就可能造成反斜杠困扰。假如你需要匹配文本中的字符"\",那么使用编程语言表示的正则表达式里将需要4个反斜杠"\\\\":前两个和后两个分别用于在编程语言里转义成反斜杠,转换成两个反斜杠后再在正则表达式里转义成一个反斜杠。Python里的原生字符串很好地解决了这个问题,这个例子中的正则表达式可以使用r"\\"表示。同样,匹配一个数字的"\\d"可以写成r"\d"。有了原生字符串,你再也不用担心是不是漏写了反斜杠,写出来的表达式也更直观。 |
轻轻知道的几个匹配模式
re.I(re.IGNORECASE):
忽略大小写(括号内是完整写法,下同)
M(MULTILINE): 多行模式,改变'^'和'$'的行为
S(DOTALL): 点任意匹配模式,改变'.'的行为 |
备注:
1、match(pattern, string, flags=0) 从起始位置开始根据模型去字符串中匹配指定内容,匹配单个
正则表达式
要匹配的字符串
标志位,用于控制正则表达式的匹配方式
import re
obj = re.match('\d+', '123uuasf')
if obj:
print(obj.group()) |
2、search(pattern, string, flags=0) 根据模型去字符串中匹配指定内容,匹配单个
import re
obj = re.search('\d+', 'u123uu888asf')
if obj:
print(obj.group() |
3、group和groups
a = "123abc456"
print(re.search("([0-9]*)([a-z]*)([0-9]*)",
a).group())
print(re.search("([0-9]*)([a-z]*)([0-9]*)",
a).group(0))
print(re.search("([0-9]*)([a-z]*)([0-9]*)",
a).group(1))
print(re.search("([0-9]*)([a-z]*)([0-9]*)",
a).group(2))
print(re.search("([0-9]*)([a-z]*)([0-9]*)",
a).groups()) |
4、findall(pattern, string, flags=0)
上述两中方式均用于匹配单值,即:只能匹配字符串中的一个,如果想要匹配到字符串中所有符合条件的元素,则需要使用
findall。
import re
obj = re.findall('\d+', 'fa123uu888asf')
print(obj) |
5、sub(pattern, repl, string, count=0, flags=0)
用于替换匹配的字符串
content = "123abc456"
new_content = re.sub('\d+', 'sb', content)
# new_content = re.sub('\d+', 'sb', content, 1)
print(new_content) |
相比于str.replace功能更加强大
6、split(pattern, string, maxsplit=0, flags=0) 根据指定匹配进行分组
content = "'1
- 2 * ((60-30+1*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2)
)'"
new_content = re.split('\*', content)
# new_content = re.split('\*', content, 1)
print(new_content) |
content = "'1
- 2 * ((60-30+1*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2)
)'"
new_content = re.split('[\+\-\*\/]+', content)
# new_content = re.split('\*', content, 1)
print(new_content) |
inpp = '1-2*((60-30
+(-40-5)*(9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14
)) - (-4*3)/ (16-3*2))'
inpp = re.sub('\s*','',inpp)
new_content = re.split('\(([\+\-\*\/]?\d+[\+\-\*\/]?\d+){1}\)',
inpp, 1)
print(new_content) |
相比于str.split更加强大
7、匹配url地址
res = re.findall('www.(?:\w+).com','www.baidu.com')
print(res) #['www.baidu.com'] |
14、paramiko
paramiko是一个用于做远程控制的模块,使用该模块可以对远程服务器进行命令或文件操作,值得一说的是,fabric和ansible内部的远程管理就是使用的paramiko来现实。
(1)下载安装
pycrypto,由于 paramiko 模块内部依赖pycrypto,所以先下载安装pycrypto
pip3 install pycrypto
pip3 install paramiko |
(2)模块使用
a、执行命令 - 用户名+密码
#!/usr/bin/env
python
#coding:utf-8
import paramiko
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy (paramiko.AutoAddPolicy())
ssh.connect (hostname='192.168.88.136', port=22, username='test', password='123')
stdin, stdout, stderr = ssh.exec_command('df
-h')
print(stdout.read())
ssh.close() |
b、执行命令 - 密钥
import paramiko
private_key_path = '/home/auto/.ssh/id_rsa'
key = paramiko.RSAKey.from _private_key_file (private_key_path)
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy (paramiko.AutoAddPolicy())
ssh.connect (hostname='192.168.88.136', port=22,username= 'test', password=key)
stdin, stdout, stderr = ssh.exec_command('df
-h')
print(stdout.read())
ssh.close() |
c、上传或下载文件 - 用户名+密码
#上传
import os,sysimport paramiko
t = paramiko.Transport(('192.168.88.136',22))
t.connect(username='test',password='123')
sftp = paramiko.SFTPClient.from_transport(t)
sftp.put('/tmp/test1.py','/tmp/test2.py')
t.close()
#下载
import os,sysimport paramiko
t = paramiko.Transport(('192.168.88.136',22))
t.connect(username='test',password='123')
sftp = paramiko.SFTPClient.from_transport(t)
sftp.get('/tmp/test1.py','/tmp/test2.py')
t.close() |
d、上传或下载文件 - 密钥
#上传
import paramiko
pravie_key_path = '/home/auto/.ssh/id_rsa'
key = paramiko.RSAKey.from_private_key_file(pravie_key_path)
t = paramiko.Transport(('192.168.88.136',22))
t.connect(username='wupeiqi',pkey=key)
sftp = paramiko.SFTPClient.from_transport(t)
sftp.put('/tmp/test3.py','/tmp/test4.py')
t.close()
#下载
import paramiko
pravie_key_path = '/home/auto/.ssh/id_rsa'
key = paramiko.RSAKey.from_private_key_file(pravie_key_path)
t = paramiko.Transport(('192.168.88.136',22))
t.connect(username='test',pkey=key)
sftp = paramiko.SFTPClient.from_transport(t)
sftp.get('/tmp/test3.py','/tmp/test4.py')
t.close() |
15、requests
Python标准库中提供了:urllib等模块以供Http请求,但是,它的 API 太渣了。它是为另一个时代、另一个互联网所创建的。它需要巨量的工作,甚至包括各种方法覆盖,来完成最简单的任务。
(1)发送GET请求
import urllib.request
f = urllib.request.urlopen('http:// www.webxml.com.cn// webservices/ qqOnlineWebService.asmx/ qqCheckOnline? qqCode=424662508')
result = f.read().decode('utf-8') |
(2)发送携带请求头的GET请求
import urllib.request
req = urllib.request.Request('http://www.example.com/')
req.add_header('Referer', 'http://www.python.org/')
r = urllib.request.urlopen(req)
result = f.read().decode('utf-8') |
备注:
更多见Python官方文档:https://docs.python.org/3.5/library/urllib.request.html#module-urllib.request
Requests 是使用 Apache2 Licensed 许可证的 基于Python开发的HTTP
库,其在Python内置模块的基础上进行了高度的封装,从而使得Pythoner进行网络请求时,变得美好了许多,使用Requests可以轻而易举的完成浏览器可有的任何操作。
(1)安装模块
(2)使用模块
a、GET请求
①无参数实例
import requests
ret = requests.get('https://github.com/timeline.json')
print(ret.url)
print(ret.text)
②有参数实例
import requests
payload = {'key1': 'value1', 'key2': 'value2'}
ret = requests.get("http://httpbin.org/get",
params=payload)
print(ret.url)
print(ret.text) |
b、POST请求
①基本POST实例
import requests
payload = {'key1': 'value1', 'key2': 'value2'}
ret = requests.post("http://httpbin.org/post",
data=payload)
print(ret.text)
②发送请求头和数据实例
import requests
import json
url = 'https://api.github.com/some/endpoint'
payload = {'some': 'data'}
headers = {'content-type': 'application/json'}
ret = requests.post(url, data=json.dumps(payload),
headers=headers)
print(ret.text)
print(ret.cookies) |
c、其他请求
requests.get(url,
params=None, **kwargs)
requests.post(url, data=None, json=None, **kwargs)
requests.put(url, data=None, **kwargs)
requests.head(url, **kwargs)
requests.delete(url, **kwargs)
requests.patch(url, data=None, **kwargs)
requests.options(url, **kwargs) |
备注:
以上方法均是在此方法的基础上构建 requests.request(method, url, **kwargs)
更多requests模块相关的文档见:http://cn.python-requests.org/zh_CN/latest/
(3)Http请求和XML实例
实例1:检测QQ账号是否在线
import urllib
import requests
from xml.etree import ElementTree as ET
# 使用内置模块urllib发送HTTP请求,或者XML格式内容"""
f = urllib.request.urlopen('http://www.webxml.com.cn//
webservices/qqOnlineWebService.asmx/ qqCheckOnline? qqCode=424662508')
result = f.read().decode('utf-8')
# 使用第三方模块requests发送HTTP请求,或者XML格式内容
r = requests.get('http://www.webxml.com.cn //webservices/
qqOnlineWebService.asmx/ qqCheckOnline? qqCode=424662508')
result = r.text
# 解析XML格式内容
node = ET.XML(result)
# 获取内容
if node.text == "Y":
print("在线")
else:
print("离线") |
实例2:查看火车停靠信息
import urllib
import requests
from xml.etree import ElementTree as ET
# 使用内置模块urllib发送HTTP请求,或者XML格式内容
f = urllib.request.urlopen ('http://www.webxml.com.cn/ WebServices
/TrainTimeWebService.asmx / getDetailInfoByTrainCode?
TrainCode= G666&UserID=')
result = f.read().decode()
# 使用第三方模块requests发送HTTP请求,或者XML格式内容
r = requests.get ('http://www.webxml.com.cn/
WebServices/ TrainTimeWebService.asmx/ getDetailInfoByTrainCode?
TrainCode =G666&UserID=')
result = r.text
# 解析XML格式内容
root = ET.XML(result)
for node in root.iter ('TrainDetailInfo'):
print(node.find ('TrainStation').text, node.find('StartTime').text, node.tag,node.attrib) |
16、subprocess
(1)call #执行命令,返回状态码
subprocess.call("ls
-l", shell=False)
subprocess.call("ls -l", shell=True) |
(2)check_call #执行命令,如果执行状态码是 0 ,则返回0,否则抛异常
subprocess.check_call("ls
-l")
subprocess.check_call("ls -l", shell=True) |
(3)check_output #执行命令,如果状态码是 0 ,则返回执行结果,否则抛异常
subprocess.check_output(["echo",
"Hello World!"])
subprocess.check_output("ls -l", shell=True) |
(4)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 -> 同意使用
startupinfo与createionflags只在windows下有效,将被传递给底层的CreateProcess()函数,用于设置子进程的一些属性,如:主窗口的外观,进程的优先级等等
|
a、执行普通命令
import subprocess
ret1 = subprocess.Popen(["mkdir","t1"])
ret2 = subprocess.Popen("mkdir t2",
shell=True) |
b、终端输入的命令分为两种:
输入即可得到输出,如:ifconfig
输入进行某环境,依赖再输入,如:python
import subprocess
obj = subprocess.Popen("mkdir test",
shell=True, cwd='/home/',) |
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) |
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) |
|