内容
1.模块的调用
不涉及包
import time,xxx
#通过搜索路径找到time.py,xxx.py文件后,将文件里代码执行后,赋给time、xxx
from time import time,xxx
#加载方法,注意与自己写的函数重名冲突问题。
from time import *
from time import time as axe
涉及包
包(package):按目录来组织文件的方法,创建包后,包下自动有__init__.py文件。
import package
#调用执行__init__.py文件,并未与其他模块联系
from package import main
#联系包下的main模块
from package.package1 import logger
#调用package下package1里的logger模块
from package.package1.logger import logger
#调用package下package1的logger模块的logger方法
from . import *
#.相对导入
#*要在导入的包下的__init__文件里写入 __all__ = ['module1','module2']
2.目录组织方式
foo项目
————————————————————————————
Foo/
|------bin/
| |------foo
|
|------foo/
| |------tests/
| | |------__init__.py
| | |------test_main.py
| |
| |------__init__.py
| |------main.py
|
|------docs/
| |------conf.py
| |------abc.rst
|
|------setup.py
|------requirements.txt
|------README
————————————————————————————
bin/:存放项目的一些可执行文件,也可以命名为script/之类的
foo/:存放项目的所有源代码
(1)源代码中的所有模块、包都应放在此目录,不要置于顶层目录
(2)其子目录tests/存放单元测试代码
(3)程序的入口最好命名为main.py
docs/:存放一些文档
setup.py:安装、部署、打包的脚本
requirements.txt:存放软件依赖的外部python包列表
README:项目说明文件
————————————————————————————
关于README:
简述项目信息,让读者快速了解项目。需要说明几个事项:
(1)软件定位,软件的基本功能
(2)运行代码的方法:安装环境,启动命令等
(3)简要的使用说明
(4)代码目录结构说明,更详细点可以说明软件的基本思想
(5)常见问题说明
————————————————————————————
环境变量
在package下的bin.py文件里调用package2中的main模块,而main模块里又调用了packa2的logger模块,from package2 import logger,这里要注意一个问题,这种跨包,pycharm会自动加入环境路径,但是在cmd下,不会这样,会报错,找不到logger模块,因此要自己把路径写入。
import sys,os
BASE_DIR=os.path.dirname(os.path.dirname(os.path.dirname(__filr__)))
sys.path.append(BASE_DIR)
这样会把最外层的目录路径写入环境路径里,就可以顺利执行不报错啦
————————————————————————————
‘name’==‘main’
if __name__ == '__main__':
#测试代码
pass
本文件运行时,__name__就等于’main’,程序从此开始运行,相当于c里的main函数,而在别的文件如foo.py调用这个模块时,__name__等于’foo’,这样就可以巧妙地用来测试模块代码而不影响整个体系啦
3.序列化:
什么是序列化:把对象(变量)从内存中变成可存储或传输的过程称之为序列化,在python中pickling,在其他语言中也被称之为serialization、marshalling、flagtening等等,都是一个意思。
序列化之后,就可以把序列化后的内容写入磁盘,或者通过网络运输到别的机器上。
反过来,把变量内容从序列化的对象重新读到内存里称之为反序列化,即unpickling。
json
如果要在不同编程语言之间传递对象,就必须把对象序列化为标准格式,比如xml,但更好的方法是序列化为json,因为json表示出来就是一个字符串,可以被所有语言读取,也可以方便地存储到磁盘或者通过网络传输。json不仅是标准格式,并且比xml更快,而且可以直接在web页面中读取,非常方便。
但是json在python里的序列化操作时,并不支持set类型,以及函数和类,同时在反序列化操作时可能会导致数据丢失:(tuple丢失)
json把python里的绝大部分数据类型,转化为字符串
pickle把python里的所有数据类型,转换为字节串(bytes类型)
json和pickle都是一次性写入,一次性读取
但是json不能多次对同一个文件序列化
而pickle可以多次对同一个文件序列化
json和pickle都有dumps()、loads()、dump()、load()方法,用法基本一样,注意pickle只能存取bytes类型。
————————————————————————————
存
1.dumps
import json
dic = {'name':'axe','age':'21'}
data = json.dumps(dic)
f = open('JSON_text','w')
f.write(data)
f.close()
2.dump
import json
dic = {'name':'axe','age':'21'}
f = open('JSON_text','w')
json.dump(dic,f)
f.close()
————————————————————————————
取
1.loads
import json
f=open('JSON_text','r')
data = f.read()
data = json.loads(data)
print(data['name'])
2.load
import json
f=open('JSON_text','r')
data = json.load(f)
print(data['name'])
————————————————————————————
pickle
无法于别的语言沟通,只能在python里,但是可以对函数和类进行序列化,而json不可以。
pickle支持python里的所有数据类型,把所有数据类型转换成字节码
可以多次对同一个文件序列化
————————————————————————————
存
1.dumps
import pickle
dic = {'name':'axe','age':'21'}
data = pickle.dumps(dic)
f = open('pickle_text','w')
f.write(data)
f.close()
2.dump
import pickle
dic = {'name':'axe','age':'21'}
f = open('pickle_text','w')
pickle.dump(dic,f)
f.close()
————————————————————————————
取
1.loads
import pickle
f=open('pickle_text','r')
data = f.read()
data = pickle.loads(data)
print(data['name'])
2.load
import pickle
f=open('pickle_text','r')
data = pickle.load(f)
print(data['name'])
————————————————————————————
shelve
比pickle简单,只有一个open函数,返回类似字典的对象,可读可写:key必须为字符串,而值可以是python所支持的数据类型。
————————————————————————————
存
impot shelve
f=shelve.open(r'SHELVE_text')
f['info']={'name':'axe','age':'21'}
存好后以三种文件格式存储:SHELVE_text.bak、SHELVE_text.dat、SHELVE_text.dir
————————————————————————————
取
import shelve
f=shelve.open('SHELVE_text')
data=f.get('info')
#data=f['info']
print(data)
————————————————————————————
xml
与json差不多,但是json更好用
xml也是所有语言都支持(老旧了)
————————————————————————————
格式
<data>
<country name='Liechtenstein'>
<rank update='yes'>2</rank>----update=‘yes’是属性
<year>2020</year>----2020是文本内容
<gdppc>141100</gdppc>----gdppc是标签
<neighbor name='Austria' direction='E'/>----自闭合
<neighbor name='Switzerland' direction='W'/>
</country>
</data>
————————————————————————————
操作
import xml.etree.ElementTree as ET
tree=ET.parse('xml_test')#解析文件
root=tree.getroot()
————————————————————————————
操作
print(root.tag)#最外层的标签(根)
for child in root:#遍历xml文档
print(child.tag,child.attrib)
for i in child:
print(i.tag,i.text)
for node in root.iter('year'):#只遍历year节点
print(node.tag,node.text)
————————————————————————————
修改
for node in root.iter('year'):
new_year=int(node.text)+1
node.text=str(new_year)
node.set('update','yes')
tree.write('xml_text')
————————————————————————————
删除
for country in root.findall('country'):
rank=int(country.find('rank').text)
if rank > 50:
root.remove(country)
tree.write('ouput.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')
age.text='21'
et=ET.ElementTree(new_xml)
et.write('test.xml',encoding='utf-8',xml_declaration=True)
ET.dump(new_xml)
————————————————————————————
4.time
datetime
time.time()#时间戳,1970年至今的时间,单位秒
time.sleep(3)#程序停止3秒,cpu不工作
time.clock()#计算cpu工作时间
time.gmtime()
#UTC时间,结构化的一个时间:time.struct_time(tm_year=2020,......)
time.localtime()#本地时间,结构化时间
time.strftime('%Y--%m--%d %H%M%s',struct_time)
#将结构化时间转换成字符串格式化时间
a=time.strptime('2020--04--08 22:30:45','%Y%m%d %H%M%s')
#将字符串时间转换成结构化时间,赋值给a,a.tm_year-->取出结构化时间里的tm_year
time.ctime()#返回一个Thu Sep 8 18:28:18 2020这种格式的时间
time.ctime(12346575456)#计算从1970开始,算上时间戳的时间。
time.mktime(time.localtime())#将元组的结构化时间转换成时间戳。
datetime.datetime.now()#格式化时间:2020--04--08 22:30:45
5.random
随机数模块
random.random()#0~1的随机浮点数
random.randint(1,8)#1到8,包括8在内的一个随机整数
random.choice('hello')#从序列hello里随机取一个元素
random.shuffle(序列)#将序列顺序打乱,返回None,而序列顺序已被打乱
random.sample(['123',4,[1,2]],2)#从序列里随机取2个元素
random.randrange(1,3)#从1到3,不包括3的一个随机整数
————————————————————————————
生成验证码:
def v_code:
code=''
for i in range(5):
add=random.choice([random.randrange(10),chr(
random.randrange(65,91))])
''.join([code,add])
print(code)
v_code()
————————————————————————————
6.os
对操作系统的调用
os.urandom(16)
#返回16位随机字符
os.getcwd()
#获取当前目录
os.chdir('dirname')
#改变当前工作目录,相当于shell下的cd
os.curdir
#访问当前目录:'.'
os.pardir
#获取当前目录的父目录字符串名:'..'
os.makedirs('dirname1/dirname2')
#可生成多层递归目录,如下一条所示
os.makedirs('abc\\axe\\aint')
os.removedirs('abc\\axe\\aint')
#若aint目录为空,则删除,并递归到上一级目录,若也为空,则删除,继续下去
os.mkdir('dirname')
#生成单级目录,相当于shell中mkdir filename
os.mkdir('dirname\\axe')
#在dirname下生成一个单级目录
os.rmdir('dirname')
#删除空目录,若目录不为空,则无法删除,报错;相当于shell中rmdir dirname
os.listdir('dirname')
#列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印出来
os.remove('x.txt')
#删除x.txt文件,只能删除文件,不能删除目录
os.rename('oldname','newname')
#重命名文件/目录
info = os.stat('path/filename')
#获取文件/目录信息,info是os stat_result(....st_size=0,st_atime=82891891,st_mtime=19293873),通过info.st_size这种格式可以获取文件大小
os.path.getsize(filename)
#获取文件大小
os.sep
#输出当前系统路径分隔符,跨系统应用用的到,win:/,linux:\
os.linesep
#输出当前平台使用的行终止符,win:\r\n,linux:\n,mac:\r
os.pathsep
#输出用于分割文件路径的字符串,win-->; linux-->:
os.name
#输出字符串指示当前使用的平台。win:'nt',linux:'posix'
os.system('shell command')
#执行shell命令,直接显示
os.environ
#获取环境变量,字典形式
os.path.abspath('./abc')
#返回path规范化的绝对路径
os.path.spilt(path)
#将path分割成目录和文件名,元组形式
os.path.dirname(path)
#返回path的目录,其实就是os.path.spilt(path)的第一个元素
os.path.basename(path)
#返回path最后的文件名,如果path以/或\结尾,那么返回空值
os.path.exists(path)
#如果path存在,返回True
os.path.isabs(path)
#判断是否为绝对路径
os.path.isfile(path)
#判断是否为存在的文件
os.path.isdir(path)
#判断是否为存在的目录
os.path.getatime(path)
#返回path所指向的文件或目录的最后存取时间
os.path.getmtime(path)
#返回path所指向的文件或目录的最后修改时间
os.path.join(path,*path)
#将多个路径拼接起来后返回
os.path.join([a,b])
7.sys
与python解释器进行交互
sys.argv
#命令行参数List,第一个元素是程序本身路径
sys.exit(n)
#退出程序,正常退出是exit(0)
sys.path
#返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值
sys.platform
#返回操作系统平台名称
sys.stdout.write('please:')
#标准输出,做进度条使用,sys.stdout.flush
val=sys.stdin.readline()[:-1]
getattr(sys.modules[__name__],'operate')()
#通过字符串的方式运行__name__对应的模块里的'operate'方法
sys.argv:
在终端:
python sys_module.py post path
后面post,path是传入的程序的参数
此时sys.argv打印结果为:[‘sys_module’,‘post’,‘path’]
import time,然后sys.path---->返回time模块的搜索路径
post可以用来做下载传输
if sys.argv[1]=='post':
#下载传输的代码
pass
————————————————————————————
sys.platform,可以用来作为一个跨平台程序的判断
import os
import sys
if sys.platform == 'win32':
os.system('dir')
os.system('ls -l')
————————————————————————————
8.hashlib
md5加密算法,sha1/224/256/384/512加密算法,其中md5,sha256用的稍微多点,通过m.update(‘明文’.encode(‘utf8’))加密,m.hexdigest()取加密的结果
注意加密时,原始数据的一点点小的变化,都会导致加密结果的非常大的差异——>雪崩式变化
因此可以用来做很多东西,比如测是否有病毒,断点传输中用来判断是否已经传输过,等等
具体方法如下:
————————————————————————————
m=hashlib.md5()
m.update('hello'.encode('utf8'))
#明文是unicode类型,要转换成bytes类型,所以要解码成utf8。python的两种类型:str,bytes
print(m.hexdigest())
m.update('axe'.encode('utf8'))
m2=hashlib.md5()
m2.update('helloaxe'.encode('utf8'))
m2.hexdigest()
#m2加密的结果等同于前面m两次加密明文结果拼接到一起
————————————————————————————
s=hashlib.sha256()
s.update('hello'.encode('utf8'))
print(s.hexdigest())
————————————————————————————
hmac
可以用来替代hashlib模块,用来验证客户端连接的合法性
import hmac,os
h = hmac.new(b'axe',os.urandom(32))
#'axe'是密钥
ret = h.digest()
#ret是bytes类型,在网络操作里,直接传过去就可以了,然后进行对比验证
9.logging
日志模块,基本用的时候直接复制粘贴就可以了
只输出在屏幕上,以下五个级别由低到高
logging.debug('debug message')
logging.info("info message")
logging.warning('warning message')#默认从warning级别开始打印在屏幕上
logging.error('error message')
logging.critical('caritical message')
————————————————————————————
灵活配置后,不在屏幕上输出,输出到文件里(二选一的)
logging.basicConfig(level=logging.DEBUG ,
format='%(astime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s' ,
datefmt='%a,%d %b %Y %H:%M:%s' ,
#handlers=[fh,ch],
filename='/tmp/test.log' ,
filemode='w')
logging.debug('debug message')
logging.info(info message")
logging.warning('warning message')
logging.error('error message')
logging.critical('caritical message')
#没有filename参数,则打印在屏幕上
#lineno指程序所在行号
#filemode若不写,则默认‘a’模式
#datefmt:日期时间格式
————————————————————————————
实现既打印在屏幕上,又输出到文件里
import logging
fh=logging.FileHandler('/tmp/test.log')
#创建一个handler,用于写入文件
ch=logging.StreamHandler()
#创建一个handler,用于输出到控制台,也就是屏幕上
#formatter=logging.Formatter('%(astime)s-%(name)s-%(levelname)s-%(message)s')
##调整输出格式
#fh.setFormatter(formatter)
#ch.setFormatter(formatter)
#logger=logging.getLogger()
##创建一个logger对象,用于融汇两个功能
#logger.addHandler(fh)
#logger.addHandler(ch)
#logger.setLevel(logging.DEBUG)
##设置输出级别
logging.basicConfig(level=logging.DEBUG ,
format='%(astime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s' ,
datefmt='%a,%d %b %Y %H:%M:%s' ,
handlers=[fh,ch],
filename='/tmp/test.log' ,
filemode='a')
logging.debug('debug message')
logging.info("info message")
logging.warning('warning message')
logging.error('error message')
logging.critical('caritical message')
————————————————————————————
切割日志
from logging import handlers
import logging
sh = logging.StreamHandlers()
rh = handlers.RotatingFileHandler('mylog.log',maxBytes = 1024,backCount = 5)
#backCount=5:只保留5个,到第6个会删除第1个,滚动
fh = handlers.TimedRotatingFileHandler(filename = 'mylog.log',when = 's',interval = 5,encoding = 'utf8')
#when='s':秒,interval=5:每5秒
logging.basicConfig(level=logging.DEBUG ,
format='%(astime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s' ,
datefmt='%a,%d %b %Y %H:%M:%s' ,
handlers=[sh,rh,fh],
filename='mylog.log' ,
filemode='a')
logging.debug('debug message')
logging.info(info message")
logging.warning('warning message')
logging.error('error message')
logging.critical('caritical message')
10.configparser
用于生成和修改常见配置文件
————————————————————————————
文件内容格式:
[DEFAULT]
ServerAxeInterval=22
compression=yes
compressionLevel=9
[bitbucket.org]
user=axe
————————————————————————————
写入
import configparser
#取到一个文件配置对象
config=configparser.ConfigParser()
#存入相当于一个大字典,里嵌套一个小字典,DEFAULT是键,后面字典是值
config['DEFAULT']={'ServerAxeInterval':'22','compression':'yes','compressionLevel':'9'}
config['bitbucket.org']={'user':'axe'}
#创建的或者修改的必须要写入文件里
with open('example.ini','w') as configfile:
config.write(configfile)
————————————————————————————
读
#与文件关联起来
config.read('example.ini')
#取出除DEFAULT外的内容,打印在屏幕上
config.sections()
#取出DEFAULT块的内容
config.defaults()
#判断bitbucket.org块是否在文件里
'bitbucket.org' in config
#打印bitbucket.org下的内容,还包括DEFAULT下的内容
for key in config['bitbucket.org']
print(key)
with open('example.ini','w') as configfile:
config.write(configfile)
————————————————————————————
删
#删除bitbucket.org块
config.remove_section('bitbucket.org')
#查bitbucket.org是否还在内容里
config.has_section('bitbucket.org')
#删除块下的键值对
config.remove_option('bitbucket.org','user')
#将改后的内容重新输出成一个i.cfg文件,若与原文件名一致,则覆盖
config.write(open('i.cfg','w'))
————————————————————————————
改
config.set('bitbucket.org','user','aintdone')
#改块下键对应的值
————————————————————————————
11.collections
包含了一些容器类型
- namedtuple():命名元组
- defaultdict():默认值字典
- Counter():计数器
from collections import namedtuple,defaultdict,Counter
#namedtuple
Rectangle = namedtuple('Rectangle is',['length','width'])
r = Rectangle(10,5)
print(r.length)
print(r.width)#通过属性访问元组的元素
#创建字典的方式
d = {'name':'axe','age':21}
d = dict([('name','axe'),('age',21)])
d = {k:v for k,v in [('name','axe'),('age',21)]}
#defaultdict
def foo():
return 'axe11'
d = defaultdict(foo,name = 'axe',age = 21)
print(d['name'])#axe
print(d['age'])#21
print(d['addr'])#字典里无,打印结果为axe11,同时将{'addr':'axe11']添加到字典里
#defaultdict的第一个参数,自定义函数,要求不能有参数!!!
#Counter
c = Counter('asxsacsa')
#结果为:{'a':3,'c':1,'s':3,'x':1}
c.most_common(2)
#返回排名前2的键值对
12.shutil
与文件、目录相关的模块,用来代替os模块加递归一起的部分操作
拷贝文件
shutil.copy2('原文件',‘现文件’)
拷贝目录
shutil.copytree('原目录',‘新目录’,ignore = shutil.ignore_patterns(*.py))
#ignore = shutil.ignore_patterns(*.py):拷贝目录时忽略的文件
删除目录
shutil.rmtree('temp',ignore_errors = True)
#ignore_errors参数为True时,会忽略删除时的错误,如程序正在运行这样的,强制删除
移动文件/目录
shutil.move('logging模块','logging2',copy_function = shutil.copy2)
获取磁盘使用空间
total,used,free = shutil.disk_usage('.')
print('当前磁盘共:%iGB,已使用:%iGB,剩余:%iGB'%(total/1073741824,used/1073741824,free/1073741824))
压缩文件
shutil.make_archive('压缩文件夹的名字','zip','待压缩的文件夹路径')
解压文件
shutil.unpack_archive('zip文件的路径.zip','解压到目的文件夹路径')