python-模块与包,python-模块,目录:1.模块 2.


目录: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下为”\r\n”,Linux下为”\n”

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() 全部匹配

以上方法,括号内两个参数,第一个是正则规则,规则用‘’引起来,第二个是数据

贪婪匹配:在满足匹配时,匹配尽可能长的字符串,默认情况下采用贪婪匹配

非贪婪匹配:在满足匹配时,匹配尽可能短的字符串,使用?开头来表示非贪婪匹配

元字符是正则最核心的内容

. 通配符,可以匹配除换行符\n以外的任意一个符号

^ 匹配字符开头

$ 匹配字符结尾

* 匹配*前的字符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]

\b 匹配一个特殊字符边界,比如空格 & # 等

\A 只从字符开头匹配 等同于^

\Z 匹配字符结尾,等同于$

软件开发规范

bin 可执行文件

conf 配置文件

core 核心代码 也可以就叫项目名称,项目名称一般是用小写的

  db 数据库文件

docs 说明文档

  lib 库文件,放自己制作的自定义模块或包

log 日志文件

README 文本文件

1.软件定位,软件的基本功能

2.运行代码的方法:安装环境、启动命令等

3.简要的使用说明

4.代码目录结构说明,更详细点可以说明软件的基本原理

5.常见问题说明

python-模块与包

评论关闭