python-模块与包
Posted interstellar-cooper
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python-模块与包相关的知识,希望对你有一定的参考价值。
目录:1.模块 2.包 3.绝对导入与相对导入 4.time模块 5.random模块 6.os模块 7.sys模块 8.json&pickle模块 9.shelve模块 10.xml模块 11.configparser模块 12. hashlib模块 13.subprocess模块 14.logging模块 15.re模块 16.软件开发规范
模块:
分类:内置模块,第三方模块,自定义模块
调用方式:
import module
from module import xxx
from module.xx.xx import xx as rename
from module.xx.xx import *
模块一旦被调用,相当于执行了其中的代码
程序在哪执行,sys.path中就默认有当前目录的路径
跨模块导入时要添加环境变量,把父级路径添加到sys.path中
import sys,os
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
sys.path打印一个列表,第一个元素是 ’ ’ 就是当前目录的路径
__file__就是当前程序的路径,pycharm里是绝对路径,python2中是相对路径
所以最好使用os.path.abspath(__file__)拿到绝对路径
if __name__==’__main__’ 该文件就当做脚本去执行
__all__=[] 列表里面写字符串形式的内容,这样from … import * 这样操作的时候*不再代表所有的内容了,只代表[]内的所有内容
包:
一个文件夹管理多个模块文件,这个文件夹就被称为包
包就是文件夹,该文件夹下有__init__.py文件
导入包的时候,会先执行包下面的__init__文件
凡是在导入的时候带 . 的, . 的左边都必须是一个包
from … import … 这种格式的时候,import后面的不能有.
from … import *这样导入包的时候,*只会导入包下面__init__文件中的内容,我们可以在这个文件中自定义__all__=[]
绝对导入与相对导入
在涉及相对导入时,package所对应的文件夹必须正确的被python解释器视为package,而不是普通文件夹
文件夹被python解释器视作package需要满足的条件:
1.文件夹中必须有__init__.py文件,该文件可以为空,但必须存在该文件
2.不能作为顶层模块来执行该文件夹中的py文件(即不能作为主函数的入口),
即用..的时候包不能跟入口程序在同一层
.代表__init__当前的目录,就是跟执行的程序入口在同一级目录,..代表__init__上一级目录
相对导入用的不多,不建议用
time模块:
python中通常有如下方式表示时间
1.时间戳 time.time() 是从1970年1月1日00:00:00开始计算到现在的秒数
2格式化的时间字符串,time.strftime(“%Y-%m-%d %X”),得到2018-04-09 17:06:32 Y改成y就显示18
3元组,即结构化时间 time.localtime() 拿到的是时间每个部分组成的一个元组,可以每一部分都取出来然后重新组合
结构化时间到字符串时间用strftime,字符串时间到结构化时间strptime
结构化时间到时间戳用mktime,时间戳到结构化时间用localtime或gmtime
字符串时间与时间戳之间不能直接转化
time.asctime()获取当前时间,格式是周 月 日 时 分 秒 年 time.ctime()
time.mktime(time.strptime(‘2021-02-01‘,‘%Y-%m-%d‘)) 实现字符串时间到时间戳的转化
即先用strptime将字符串时间转成结构化时间,再用mktime将结构化时间转成时间戳
time.strptime(字符串时间)--->结构化时间 time.mktime(结构化时间)--->时间戳
time.strftime(‘%Y-%m-%d‘,time.localtime(time.time())) 实现时间戳到字符串时间的转化
即先用localtime将时间戳转成结构化时间,再用strftime将结构化时间转成字符串时间
time.localtime(时间戳) or time.gtime(时间戳)--->结构化时间 time.strftime(结构化时间)--->字符串时间
datetime模块:
datetime.date.fromtimestamp() 把一个时间戳转成datetime日期类型
datetime.datetime.now()返回当前时间,格式是年月日时分秒
时间运算:
datetime.datetime.now() - datetime.timedelta(days = 1)
减一天,可以写days,hours,minutes,seconds,可加可减
时间替换:
d = datetime.datetime.now()
d.replace(year = 1990,month = 10)可以替换出来一个自己指定的时间
random模块:
random.random() 得到的是0~1之间的小数
random.randint(1,s) 大于等于1且小于等于s之间的整数
random.randrange(1,s) 大于等于1且小于s之间的整数,可以再加一个参数(1,8,2)2是步长的意思,从1开始,结果都是奇数
random.choice([1,’23’,(4,5)]) 1或’23’或(45),随机返回一个,里面可以放列表、字符串,返回一个
random.sample([1,’23’,(4,5)],2) 因为在最后一个位置设定了参数2,所以结果是从里面选两个组成列表,返回多个组成的列表
random.uniform(1,s) 大于1小于s的小数
random.shuffle(item) 打乱次序
random实例:
chr()括号里面加数字可以得到ASCII码中对应的字母
做一个五位数的验证码
一:
def validate():
s=‘‘
for i in range(5): 控制验证码的字母或数字个数
rNum=random.randint(0,9) randint得到一个0-9包括9的随机整数
alpha=chr(random.randint(65,90)) 先得到65-90包括90的随机整数,然后用chr得到对应的ASCII码中的字母
res=random.choice([rNum,alpha]) choice从整数或字母中随机选出一个赋值给res括号里面必须写列表的形式
s+=str(res)
return s
print(validate())
二:
num = string.digits 拿到0-9
alpha = string.ascii_lowercase 拿到小写的a-z
s = alpha + num 把a-z跟0-9组成一个字符串
‘’.join(random.sample(s,5))先用random.sample拿到一个五个元素组成的列表,再用join方法把列表转成字符串
string模块:
string.digits 返回字符串格式的‘0123456789‘
string.ascii_letters 返回所有的小写字母和大写字母组成的字符串
string.ascii_lowercase 返回所有小写字母组成的字符串
os模块:
os模块是与操作系统交互的一个接口
os.getcwd()获取当前工作目录,即当前python脚本所在的目录路径
os.chdir(“dirname”)改变当前脚本工作目录,相当于shell下的cd,没有返回值
os.curdir返回当前目录:(’.’)
os.pardir获取当前目录的父目录字符串名:(‘..’)
os.remove() 删除一个文件
os.removedirs(‘dirname1’)若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,以此类推
os.mkdir(‘dirname’)生成单级目录,相当于shell中mkdir dirname
os.makedirs(‘dirname1/dirname2’)可生成多层递归目录
os.rmdir(‘dirname’)删除单级目录,若目录不为空则无法删除,报错 ,相当于shell中remdir dirname
os.listdir(‘dirname’)列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印
os.rename(‘oldname’,’newname’)重命名文件/目录
os.stat(‘path/filename’)获取文件/目录信息
os.sep 输出操作系统特定的路径分隔符,win下为”\”,Linux下为”/”
os.linesep输出当前平台使用的行终止符,win下为” ”,Linux下为” ”
os.pathsep输出用于分割文件路径的字符串,win下为;,Linux下为:
os.name输出字符串指示当前使用平台win->’nt’ Linux->’posix’
os.system(“bath 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(pash)返回path最后的文件名,如果path以/或结尾,那么返回空值,即os.path.split(path)的第二个元素
os.path.exists(path)如果path存在,返回True,不存在返回False
os.path.normpath(path) 标准化路径名,合并多余的分隔符和上层引用,在windows平台上还会把斜线转换成反斜线
os.path.isabs(path)如果path是绝对路径,返回True
os.path.isfile(path)如果path是一个存在的文件,返回True
os.path.isdir(path)如果path是一个存在的目录,返回True,用..的时候会自动往前走三级目录
os.path.join(path1[,path2[,…]])将多个路径组合后返回,第一个绝对路径之前的参数将被忽略
os.path.getatime(path)返回path所指向的文件或者目录的最后访问时间
os.path.getmtime(path)返回path所指向的文件或者目录的最后修改时间
os.path.getsize(path)返回path的大小
os.walk的用法:
def file_name(file_dir):
for root, dirs, files in os.walk(file_dir):
print(root) #当前目录路径
print(dirs) #当前路径下所有子目录
print(files) #当前路径下所有非目录子文件
sys模块:
sys.argv 命令行参数List,第一个元素是程序本身路径
sys.exit(n)退出程序,正常退出时exit()
sys.version获取python解释程序的版本信息
sys.maxint获取最大的int值
sys.path返回模块的搜索路径,是一个列表,初始化时使用pythonpath环境变量的值
sys.plaform返回操作系统平台名称
sys.modules 返回内存里面都导入了哪些模块
shutil模块:
shutil.copyfileobj() 将文件内容拷贝到另一个文件中,该操作需要打开文件
shutil.copyfileobj(open(‘old.xml‘,‘r‘),open(‘new.xml‘,‘w‘))
shutil.copyfile() 拷贝文件,目标文件无需存在,该操作无需打开文件,就直接写文件名就可以
shutil.copymode() 拷贝权限,目标文件必须存在
shutil.copystat() 拷贝状态的信息,目标文件必须存在
shutil.copy() 拷贝文件和权限
shutil.copy2() 拷贝文件和状态信息
shutil.copytree() 递归着去拷贝文件夹,要拷贝生成的新目录不能存在,不然会报错
shutil.copytree(‘package‘,‘pack2‘,ignore=shutil.ignore_patterns("__init__.py"))
第一个元素是要拷贝的文件夹,第二个元素师要生成的新目录
第三个元素是symlinks=False,一般默认是这样的,就不用写了
第四个元素是排除的意思,在拷贝的时候,哪些内容不拷贝,写到这里面
shutil.rmtree() 递归着去删除文件
shutil.move() 递归着去移动文件,类似于mv命令,相当于重命名
shutil.make_archive() 创建压缩包并返回文件路径
括号里面可以放的参数:
base_name: 压缩包的文件名,也可以是压缩包的路径,只是文件名时,则保存到当前目录,否则保存到指定路径
format: 压缩包种类,zip,tar,bztar,gztar
root_dir: 要压缩的文件夹路径(默认是当前目录)
owner: 用户,默认是当前用户
group: 组,默认是当前组
logger: 用于记录日志,通常是logging.Logger对象
shutil.make_archive(‘data_bak‘,‘gztar‘,root_dir=‘/data‘)
将data下的文件打包到data_bak目录下
json&pickle模块:
什么叫序列化?
序列化是指把内存里的数据类型转变成字符串,以使其能存储到硬盘或网络传输到远程,因为硬盘或网络传输只接受bytes
把字符转成内存数据叫做反序列化
序列化本身就是一次的,dump一次,load一次,如果dump两次,那load的时候就会报错,dump多次不会报错
json,用于字符串和python数据类型之间进行转换,字典格式的json字符串,第一个key必须用""双引号,文件后缀是.json
序列化完了是字符串的格式,就可以用于存储和网络传输了
pickle,用于python特有的类型和python的数据类型之间进行转换,文件后缀是.pkl,序列化完了就直接是bytes的格式
所以用pickle的时候,关于文件的操作要注意用‘rb’/‘wb‘
两者用法完全一样
两者都有四个功能,dumps、dump、loads、load
pickle.dumps()将数据通过特殊的形式转换成只有python语言认识的bytes格式,括号中放数据
pickle.dump() 将数据通过特殊的形式转换成只有python语言认识的bytes格式,并写入文件,括号中放两个参数,一个是数据,一个是文件句柄
json.dumps()将数据通过特殊的形式转换成所有程序语言都认识的字符串
json.dump() 将数据通过特殊的形式转换成所有程序语言都认识的字符串,并写入文件,括号中放两个参数,一个是数据,一个是文件句柄
文件句柄需要是写模式的
loads是反序列化的过程,与dumps对应
load与dump对应
d1 = json.dumps(data) 将data序列化成字符串格式并赋值给d1
d2 = json.loads(d1) 将序列化得到的d1反序列化成原来的数据类型并赋值给d2
f1 = open(‘test.json‘,‘w‘) 打开要把数据写入的文件,读模式
json.dump(data,f1) 将data序列化成字符串格式,并写入到文件中
f2 = open(‘test.json‘,‘r‘) 打开要读取数据的文件,读模式
d3 = json.load(f2) 将文件f2中字符串格式的内容反序列化成原来的数据类型并赋值给d3
load括号里放文件句柄,loads括号里放bytes格式的对象,也可以放f.read()
json与pickle的比较:
json:跨语言、体积小,但是只支持int、str、list、tuple、dict
pickle:专为python设计,支持python所有数据类型,但只能在python中使用,存储数据占空间大
json.dumps()与json.loads() 只是把数据类型转成字符串并保存到内存里,其意义在于:
把内存数据通过网络共享给远程
定义了不同语言之间的交互规则:
1.纯文本,坏处是不能共享复杂的数据类型
2.xml,坏处是占空间大
3.json,简单,可读性好,跨语言
shelve模块:
为了解决json和pickle只能dump一次的问题
是对pickle进行了封装,pickle是python独有的,所以shelve只能在python中使用
import shelve
f = shelve.open(‘shelve_test‘) #打开一个文件
names = [‘alex‘,‘rain‘,‘test‘]
info = {‘name‘:‘alex‘,‘age‘:22}
f[‘names‘] = names #持久化列表
f[‘info‘] = info #持久化字典
f.close()
xml模块:
是实现不同语言或程序之间进行数据交换的协议
在各个语言中都支持
configparser模块:
用于生成和修改常见配置文档
hashlib模块:
Hash:一种将任意长度的消息压缩到某一个固定长度的消息摘要的函数
用于信息安全领域中加密算法,hash就是找到一种数据内容与数据存放地址之间的映射关系
MD5:输入任意长度的消息,经过处理,输出为128位的消息,不同的输入得到不同的结果
用于防止被篡改,防止直接看到明文,防止抵赖
特点:
压缩性,任意长度的数据算出的MD5值都是固定长度的128位
容易计算,从原数据计算出MD5值很容易
抗修改性,对于原数据进行任何改动,修改一个字节生成的MD5值区别也会很大
强抗碰撞,已知原数据与MD5值,想找到一个具有相同MD5值的数据也非常困难
MD5不可逆
SHA-1:安全哈希算法,对于长度小于2^64位的消息,SHA1会产生一个160位的消息摘要
最流行的加密算法是SHA-256
SHA-1比MD5的摘要多32比特,抵御强行攻击更强,但是缓存也要更大,运行更慢
实例:
import hashlib
m=hashlib.md5() #括号里可以加参数,就是俗称的“加盐”,提高安全性
m.update("3714".encode(‘utf-8‘))
print(m.hexdigest()) digest是二进制格式,hexdigest是十六进制格式
m.update(b"3714") #37143714 因为上面已经update了一个3714,所以这里是37143714
print(m.hexdigest())
n=hashlib.sha1()
n.update(b"3714")
print(n.hexdigest())
subprocess模块:
统一的模块来实现对 系统命令或脚本 的调用
三种执行命令的方法:
1.subprocess.run() 官方推荐
2.subprocess.call()
3.subprocess.Popen()
run()标准写法 错误 直接.stderr查看 标准输出 直接.stdout查看
subprocess.run([‘df‘,‘-h‘],stderr=subprocess.PIPE,stdout=subprocess.PIPE,check=True)
check = True ,默认是False的,这样的话如果加的命令没有也不会报错,写成True命令不存在就会报错
涉及到管道|的命令如下写,因为subprocess.PIPE也是一个类似于管道的东西
subprocess.run(‘df -h|grep disk1‘,shell=True)
shell=True的意思是这条命令直接交给系统去执行,不需要python负责解析
call() 方法 用的不多
subprocess.call([‘ls‘,‘-l‘]) 执行命令,返回命令执行状态
subprocess.check_call([‘ls‘,‘-l‘]) 执行命令,如果命令结果为0,则正常返回,否则抛异常
subprocess.gestatusoutput(‘ls /bin/ls‘) 接受字符串格式命令,返回元祖形式,第一个元素是命令执行状态
第二个元素是执行结果
subprocess.getoutput(‘ls /bin/ls‘) 接收字符串格式命令,并返回结果
Popen() 方法 这个最重要,上面的call跟run底层都是封装的Popen方法
args:shell命令,可以是字符串或者序列类型
stdin、stdout、stderr:程序的标准输入、输出和错误句柄
shell:跟run一样shell = True 就是把命令交给操作系统去执行
a = subprocess.Popen(‘Python3 guess_age.py‘,
stdout = subprocess.PIPE,
stdin = subprocess.PIPE,
stderr = subprocess.PIPE,
shell = True)
a.communicate(b‘22‘)
Popen方法在发起命令后立刻返回,而不等待命令执行结果
logging模块:
五个级别,由高到低:
logging.critical()>logging.error()>logging.warning()>logging.info()>logging.debug()
默认情况下python的logging模块将日志打印到了标准输出中,
且只显示了大于等于warning级别的日志,这说明默认的日志级别设置为warning
logging.warning(‘------warning‘) 运行就直接打印了,默认输出到屏幕
这个只能输出到文件
logging.basicConfig()函数中可通过具体参数来更改logging模块默认行为,可用参数有:
filename:用指定的文件名创建FiledHandler,这样日志会被存储在指定的文件中。
filemode:文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”。
datefmt:指定日期时间格式。
level:设置rootlogger(后边会讲解具体概念)的日志级别
format:指定handler使用的日志显示格式。
%(name)s Logger的名字
%(levelno)s 数字形式的日志级别 info是10,debug是20,warning是30,error是40,critical是50
%(levelname)s 文本形式的日志级别
%(filename)s 调用日志输出函数的模块的文件名
%(lineno)d 调用日志输出函数的语句所在的代码行
%(asctime)s 字符串形式的当前时间,默认格式是"2018-04-10 11:10:45.896"
%(message)s 用户输出的消息
日志同时输出到屏幕与文件
logger 提供了应用程序可以直接使用的接口
handler 将logger创建的日志记录发送到合适的目的输出
filter 提供了细度设备来决定输出哪条日志记录,可以理解为按照某种条件进行筛选过滤
formatter 决定日志记录的最终输出格式
logger:通常对应了程序的模块名
logger = logging.getLogger()
还可以绑定handler与filters
logger.setLevel() 指定最低日志级别,这里是设置整个logger的最低日志级别,如果handler设置的高于这个,会按照那个输出
logger.addFilter() logger.removeFilter() 添加或删除指定的filter
logger.addHandler() logger.removeHandler() 添加或删除指定的handler
logger.debug() logger.info() logger.warning() logger.error() logger.critical()
设置日志级别
handler:负责发送相关的信息到指定目的地
handler.setLevel() 指定被处理的信息级别,给handler设置级别,可以让输出到文件的跟输出到屏幕的不一样
此处设置的日志级别不能低于logger.setlevel() 设置的日志级别,不然不会生效
handler.setFormatter() 给这个handler选择一个格式
handler.addFilter() handler.removeFilter() 添加或删除一个filter对象
每个logger可以附加多个handler
常用handler:
logging.StreamHandler() 输出到屏幕
使用这个handler可以相类似与sys.stdout或sys.stderr的任何文件对象输出信息
logging.FileHandler() 输出到文件
与上者类似,用于向一个文件输出日志信息,但这个会帮你打开文件
logging.handlers.RotatingFileHandler()
与FileHandler类似,但是可以管理文件大小,当文件达到一定大小的时候,自动将当前文件改名
并生成一个新的同名日志文件继续输出
logging.handlers.TimedRotatingFileHandler()
与上面类似,但不是判断文件大小,而是间隔一定时间就自动创建新的
formatter:
日志的formatter是独立组件,可以跟handler组合
fh = logging.FileHandler(‘access.log‘) 拿到一个handler方法
formatter = logging.Formatter(‘%(asctime)s - %(name)s - %(levelname)s - %(message)s‘)
fh.setFormatter(formatter) 调用handler下面的功能,把formatter绑定到fh
实例:
import logging
def logger():
logger=logging.getLogger()
fh=logging.FileHandler(‘logger2‘)
sh=logging.StreamHandler()
formatter=logging.Formatter(‘%(asctime)s - %(name)s - %(levelname)s - %(message)s‘)
fh.setFormatter(formatter)
sh.setFormatter(formatter)
logger.addHandler(fh)
logger.addHandler(sh)
return logger
logger=logger()
logger.debug(‘debug‘)
logger.info(‘info‘)
logger.warning(‘warning‘)
logger.error(‘error‘)
logger.critical(‘critical‘)
re模块
正则表达式就是字符串的匹配规则,本质上正则要实现的是模糊匹配
re.findall() 把所有符合正则条件的内容放到一个列表中返回,有返回值
re.match() 从头开始匹配,只匹配字符串中的第一个字符,返回对象
re.search() 匹配包含,只匹配字符串中的一个,返回对象,匹配到了以后用.group()拿到要匹配的内容,分组匹配用.groups()拿到
re.split() 以匹配到的字符当做列表分隔符,可以在最后加参数限定分割次数,有点跟findall相反的意思
findall是拿到符合条件的放到一个列表中,只要符合条件的,而split是用符合条件的作为分隔符,把其他内容放到列表中
re.sub() 匹配字符并替换
re.subn() 会把替换的次数一并返回,以元组的形式
re.fullmatch() 全部匹配
以上方法,括号内两个参数,第一个是正则规则,规则用‘’引起来,第二个是数据
贪婪匹配:在满足匹配时,匹配尽可能长的字符串,默认情况下采用贪婪匹配
非贪婪匹配:在满足匹配时,匹配尽可能短的字符串,使用?开头来表示非贪婪匹配
元字符是正则最核心的内容
. 通配符,可以匹配除换行符 以外的任意一个符号
^ 匹配字符开头
$ 匹配字符结尾
* 匹配*前的字符0次或多次
+ 匹配+前一个字符一次或多次
? 匹配?前一个字符一次或零次
{m} 匹配前一个字符m次
{n,m} 匹配前一个字符n到m次
| 或
[] 字符集 如果是a[bd]c 匹配到的是abc和adc
如果字符集里面放* + ?等这种元字符,那它们就失去了原本的功能,变成一个普通字符
字符集里面可以放的符号:- 表示范围
^ 放在字符集里面表示取反,不再是以前的开始匹配
还是以前的功能,是一个转义符
() 分组匹配,按照匹配规则,匹配得到的结果优先是括号里面的内容
可以在括号开头加?:取消优先级
(?P<name>)命名分组
转义符,后面跟不同的内容有不同的意思
后面跟的是元字符则去除其特殊功能,变成普通字符 如. *
后面跟特定的普通字符实现特殊功能,如下
d 匹配数字0-9 等于[0-9] 经常用
D 匹配任何非数字字符
s 匹配任何空白字符
S 匹配任何非空白字符
w 匹配任何字母数字字符 [a-zA-Z0-9] 经常用
W 匹配任何非字母数字字符 非[a-zA-Z0-9]
匹配一个特殊字符边界,比如空格 & # 等
A 只从字符开头匹配 等同于^
匹配字符结尾,等同于$
软件开发规范
bin 可执行文件
conf 配置文件
core 核心代码 也可以就叫项目名称,项目名称一般是用小写的
db 数据库文件
docs 说明文档
lib 库文件,放自己制作的自定义模块或包
log 日志文件
README 文本文件
1.软件定位,软件的基本功能
2.运行代码的方法:安装环境、启动命令等
3.简要的使用说明
4.代码目录结构说明,更详细点可以说明软件的基本原理
5.常见问题说明
以上是关于python-模块与包的主要内容,如果未能解决你的问题,请参考以下文章