您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Model Center   Code  
会员   
   
 
     
   
 订阅
  捐助
python模块
 
   次浏览      
 2018-2-1 
 
编辑推荐:
来源于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)安装模块

pip3 install requests

(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)
   
次浏览       
相关文章

手机软件测试用例设计实践
手机客户端UI测试分析
iPhone消息推送机制实现与探讨
Android手机开发(一)
相关文档

Android_UI官方设计教程
手机开发平台介绍
android拍照及上传功能
Android讲义智能手机开发
相关课程

Android高级移动应用程序
Android系统开发
Android应用开发
手机软件测试