何为模块
1.一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀。
2.模块目的和函数,对象等一样,是为了代码的复用性而存在的。即一个py程序写了很多功能,也可以被其他py程序调用。被调用后被作为模块,此时会产生一个pyc的文件即为这个模块的缓存文件,相当于编译了模块文件使该py模块被调用的速度变快、更便捷。
collections扩展模块
namedtuple:生成可以使用名字来访问元素内容的tuple
# from collections import namedtuple # Card = namedtuple('card',['suits','number']) # c1 = Card('红桃',2) # print(c1) # print(c1.number) # print(c1.suits)
card(suits='红桃', number=2)
2
红桃
deque:双向队列:可以完成队列完成不了的插入及队列前后双向存取
# from collections import deque # dq = deque([1,2]) # dq.append(3) # 从后面放数据 [1,2,3] # dq.appendleft(‘a’) # 从前面放数据 ['a',1,2,3] # dq.insert(2,4) #['b',1,4,2,'3'] # print(dq.pop()) # 从后面取数据 # print(dq.popleft()) # 从前面取数据 # print(dq)
队列queue:先进先出
# import queue # q=queue.Queue() # q.put([5,7]) # q.put(1) # q.put()表示放入队列 #q.get()表示从队列中取出 # q.put(2) # q.put(3) # print(q) #<queue.Queue object at 0x0000000002739CF8> # print(q.get()) #取出[5, 7] # print(q.get()) #取出1 # print(q.qsize()) #列表里有几个元素
有序字典ordered
# from collections import OrderedDict
# d = dict([('a', 1), ('b', 2), ('c', 3)])
# print(d) #dict的Key是无序的 # od = OrderedDict([('a', 1), ('b', 2), ('c', 3)]) # print(od) # OrderedDict的Key是有序的
{'a': 1, 'c': 3, 'b': 2}
OrderedDict([('a', 1), ('b', 2), ('c', 3)])
Defaultdict
使用dict
时,如果引用的Key不存在,就会抛出KeyError
。如果希望key不存在时,返回一个默认值,就可以用defaultdict
# from collections import defaultdict # d = defaultdict(lambda: 'N/A') # d['key1'] = 'abc' # d['key1'] # key1存在 'abc' # d['key2'] # key2不存在,返回默认值 'N/A'
计数器Counter
c = Counter('abcdeabcdabcaba') print c 输出:Counter({'a': 5, 'b': 4, 'c': 3, 'd': 2, 'e': 1}) #统计字符串内每个元素出现的次数
时间模块
表示时间的三种方式
(1)时间戳(timestamp) :通常来说,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量
(2)格式化的时间字符串(Format String): ‘1980-11-11’
%y 两位数的年份表示(00-99) %Y 四位数的年份表示(000-9999) %m 月份(01-12) %d 月内中的一天(0-31) %H 24小时制小时数(0-23) %I 12小时制小时数(01-12) %M 分钟数(00=59) %S 秒(00-59) %a 本地简化星期名称 %A 本地完整星期名称 %b 本地简化的月份名称 %B 本地完整的月份名称 %c 本地相应的日期表示和时间表示 %j 年内的一天(001-366) %p 本地A.M.或P.M.的等价符 %U 一年中的星期数(00-53)星期天为星期的开始 %w 星期(0-6),星期天为星期的开始 %W 一年中的星期数(00-53)星期一为星期的开始 %x 本地相应的日期表示 %X 本地相应的时间表示 %Z 当前时区的名称 %% %号本身
(3)元组(struct_time) :struct_time元组共有9个元素共九个元素:(年,月,日,时,分,秒,一年中第几周,一年中第几天等)
索引(Index) | 属性(Attribute) | 值(Values) |
---|---|---|
0 | tm_year(年) | 比如2011 |
1 | tm_mon(月) | 1 - 12 |
2 | tm_mday(日) | 1 - 31 |
3 | tm_hour(时) | 0 - 23 |
4 | tm_min(分) | 0 - 59 |
5 | tm_sec(秒) | 0 - 60 |
6 | tm_wday(weekday) | 0 - 6(0表示周一) |
7 | tm_yday(一年中的第几天) | 1 - 366 |
8 | tm_isdst(是否是夏令时) | 默认为0 |
首先,我们先导入time模块,来认识一下python中表示时间的几种格式:
import time #时间戳 print(time.time()) #格式化字符串 print(time.strftime("%Y-%m-%d %H-%M-%S")) 表示年%Y 月%m 天%d 小时%H 分%M 秒%S(大写) 2018-01-10 17-23-12
如果想自己定义时间打印:
print(time.strftime('%Y-%m-%d %H:%M:%S',(2018,1,1,10,10,10,0,0,0))) 这里需要传入9个参数且是以元组的形式传入 #时间元组:localtime将一个时间戳转换为当前时区的struct_time time.localtime() time.struct_time(tm_year=2018, tm_mon=1, tm_mday=10, tm_hour=17, tm_min=25, tm_sec=51, tm_wday=2, tm_yday=10, tm_isdst=0)
几种格式之间的转换
random模块
import random #随机小数 # random.random() # 大于0且小于1之间的小数 0.7664338498746214 # random.uniform(1,3) #大于1小于3的小数 1.6876238972879832 #随机整数 # random.randint(1,5) # 大于等于1且小于等于5之间的整数 # random.randrange(1,10,2) # 大于等于1且小于10之间的奇数 #随机选择一个返回 # random.choice([1,'23',[4,5]]) # #1或者23或者[4,5] #选择类括号内需要填入可变数据类型 #随机选择多个返回,返回的个数为函数的第二个参数 # random.sample([1,'23',[4,5]],2) # #列表元素任意2个组合 [[4, 5], '23'] #打乱列表顺序 # item=[1,2,3,4,5] # random.shuffle(item) # 打乱次序 # item [2, 4, 1, 3, 5] # random.shuffle(item) # item [5, 2, 3, 4, 1]
os模块
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下为"
",Linux下为"
"
os.pathsep 输出用于分割文件路径的字符串 win下为;,Linux下为:
os.name 输出字符串指示当前使用平台。win->'nt'; Linux->'posix'
os.system("bash command") 运行shell命令,直接显示
os.popen("bash command).read() 运行shell命令,获取执行结果
os.environ 获取系统环境变量
os.path
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.path.getsize(path) 返回path的大小
'''
注意:os.stat('path/filename') 获取文件/目录信息 的结构说明
st_mode: inode 保护模式 st_ino: inode 节点号。 st_dev: inode 驻留的设备。 st_nlink: inode 的链接数。 st_uid: 所有者的用户ID。 st_gid: 所有者的组ID。 st_size: 普通文件以字节为单位的大小;包含等待某些特殊文件的数据。 st_atime: 上次访问的时间。 st_mtime: 最后一次修改的时间。 st_ctime: 由操作系统报告的"ctime"。在某些系统上(如Unix)是最新的元数据更改的时间,在其它系统上(如Windows)是创建时间(详细信息参见平台的文档)。
sys模块
sys.argv 命令行参数List,第一个元素是程序本身路径,在操作系统上进行操作 sys.exit(n) 退出程序,正常退出时exit(0),错误退出sys.exit(1) sys.version 获取Python解释程序的版本信息 sys.path 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值 sys.platform 返回操作系统平台名称
hashlib模块
hashlib 是一个提供了一些流行的hash算法的 Python 标准库.其中所包括的算法有 md5, sha1, sha224, sha256, sha384, sha512. 另外,模块中所定义的 new(name, string=”) 方法可通过指定系统所支持的hash算法来构造相应的hash对象
摘要算法
密码的密文存储:为了提高密文的安全性,可以在内部进行加盐处理。
文件的一致性验证:验证一致性无需加盐
在下载的时候 检查我们下载的文件和远程服务器上的文件是否一致
两台机器上的两个文件 你想检查这两个文件是否相等
# import hashlib # def zhuce(): #注册 # user=input('输入注册账号') # pwd=input('请输入密码') # md5 = hashlib.md5() # a = bytes(pwd, encoding="utf-8") # md5.update(a) # string = "{}|{}".format(user, str(md5.hexdigest())) # print (string) # with open("laotie", "a",encoding="utf-8") as f: # f.write(string) # zhuce()
# def login(): #登陆 # user1=input('输入登录账号') # pwd1=input('请输入密码') # with open('laotie',encoding='utf-8')as f: # for i in f: # use,passwd=i.split('|') # md5 = hashlib.md5() # md5.update(bytes(pwd1,encoding='utf-8')) # md5_pwd = md5.hexdigest() # if user1 == use and md5_pwd == passwd: # print('登录成功') # else: # print('输入错误') # login()
logging
用于进行日志处理工作
import logging
#报错的五个等级 logging.debug('debug messages') # 排错信息 logging.info('info messages') # 正常交互信息 logging.warning('warning messages') # 警告信息 logging.error(' error messages') # 错误信息 logging.critical('critical messages') # 严重错误信息
运行后控制台输出:
WARNING:root:warning messages
ERROR:root: error messages
CRITICAL:root:critical messages
这几种信息是有级别的,默认debug和info级别的不输出,日志信息的级别顺序:CRITICAL > ERROR > WARNING > INFO > DEBUG。
函数配置:
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='log.log',
filemode='w')
logging.debug('debug messages') # 排错信息
logging.info('info messages') # 正常交互信息
logging.warning('warning messages') # 警告信息
logging.error(' error messages') # 错误信息
logging.critical('critical messages') # 严重错误信息
特点:
basicConfig: 功能比较简单,能做的事情比较少
1,不能指定文件的编码方式
2,不能同时进行文件的输入和屏幕的输出
对象配置:
logger = logging.getLogger() # 创建一个日志操作对象
filehandler = logging.FileHandler('log2.log', encoding='utf-8') # 创建一个日志文件操作句柄
streamhandler = logging.StreamHandler() # 创建一个控制台操作句柄
# 指定日志的格式
formatter = logging.Formatter('%(asctime)s-%(name)s-[line:%(lineno)d] %(levelname)s %(message)s')
logger.setLevel(logging.DEBUG) # 设置日志等级
streamhandler.setLevel(logging.INFO) # 单独设置屏幕的日志等级 不能低于logger.setLevel(logging.DEBUG)的级别
filehandler.setFormatter(formatter) # 关联格式
streamhandler.setFormatter(formatter) # 关联格式
logger.addHandler(filehandler) # 日志操作对象关联文件
logger.addHandler(streamhandler) # 日志操作对象关联屏幕
logger.debug('debug messages')
logger.info('info messages')
logger.warning('warning messages')
logger.error('error messages')
logger.critical('critical messages')
特点:
1,灵活,定制性强
2,程序解耦充分
配置参数:
logging.basicConfig()函数中可通过具体参数来更改logging模块默认行为,可用参数有:
filename:用指定的文件名创建FiledHandler,这样日志会被存储在指定的文件中。
filemode:文件打开方式,在指定了filename时使用这个参数,默认值为“a”还可指定为“w”。
format:指定handler使用的日志显示格式。
datefmt:指定日期时间格式。
level:设置rootlogger的日志级别
stream:用指定的stream创建StreamHandler。可以指定输出到sys.stderr,sys.stdout或者文件(f=open(‘test.log’,’w’)),默认为sys.stderr。
若同时列出了filename和stream两个参数,则stream参数会被忽略。
format参数中可能用到的格式化串:
%(name)s Logger的名字
%(levelno)s 数字形式的日志级别
%(levelname)s 文本形式的日志级别
%(pathname)s 调用日志输出函数的模块的完整路径名,可能没有
%(filename)s 调用日志输出函数的模块的文件名
%(module)s 调用日志输出函数的模块名
%(funcName)s 调用日志输出函数的函数名
%(lineno)d 调用日志输出函数的语句所在的代码行
%(created)f 当前时间,用UNIX标准的表示时间的浮 点数表示
%(relativeCreated)d 输出日志信息时的,自Logger创建以 来的毫秒数
%(asctime)s 字符串形式的当前时间。默认格式是 “2003-07-08 16:49:45,896”。逗号后面的是毫秒
%(thread)d 线程ID。可能没有
%(threadName)s 线程名。可能没有
%(process)d 进程ID。可能没有
%(message)s用户输出的消息
简单练习:
# import logging # def log(): # logger=logging.getLogger() # logging.basicConfig(level=logging.DEBUG,datefmt='%a, %d %b %Y %H:%M:%S',filemode='w')
# 如果想要日志等级在WARN一下,则需要basicConfig中设置level,否则系统默认是WARN ,文件模式同样如果不写系统默认是追加模式 # formatter=logging.Formatter('[%(asctime)s]-[%(filename)s]-[%(message)s]--[line:%(lineno)d][%(name)s]') # fh=logging.FileHandler('log.log',encoding='utf-8’) # fh.setFormatter(formatter) # logger.addHandler(fh) # fh.setLevel(logging.DEBUG) # ch=logging.StreamHandler() # ch.setFormatter(formatter) # logger.addHandler(ch) # ch.setLevel(logging.DEBUG) # logging.debug('debug1') # logging.info('info2') # logging.warning('warning3') # logging.error('error4') # logging.critical('critical5') # log() #使用时在外部调用即可
DEBUG:root:debug1
[2018-01-11 19:41:48,883]-[logging练习.py]-[debug1]--[line:99][root]
INFO:root:info2
[2018-01-11 19:41:48,884]-[logging练习.py]-[info2]--[line:100][root]
WARNING:root:warning3
[2018-01-11 19:41:48,884]-[logging练习.py]-[warning3]--[line:101][root]
ERROR:root:error4
[2018-01-11 19:41:48,884]-[logging练习.py]-[error4]--[line:102][root]
CRITICAL:root:critical5
[2018-01-11 19:41:48,885]-[logging练习.py]-[critical5]--[line:103][root]
模块的导入
import
import+模块名
每个模块都是一个独立的名称空间,且在一次调用后会驻留内存,下次再调用会直接调用内存中的模块(python的优化)。
# import demo 调用demo模块
# def read():
# print('哈哈哈')
# read()
# demo.read()
# print(demo.money)
结果 哈哈哈
book 100
100
#demo文件
#money = 100
#def read():
#print('book',money)
模块起别名
# import time as t #改名后,time模块的功能将被t模块替代 # print(t.time())
form ... import ...
from 模块名 import 函数名1,函数名2....
from 语句相当于import,也会创建新的名称空间,但是它可以将模块中的名字直接导入到当前的名称空间中,在当前名称空间中,
不需要使用“模块.”的方式,直接使用名字就可以了。
# from demo import read,money #调用demo模块
# read()
# print(money)
book 100
100
#demo文件
#money = 100
#def read():
#print('book',money)
如果想一次性引入math中所有的东西,还可以通过from math import *
利用 '__all__= '来调取
from demo import * read1() read2()
demo模块 __all__ = ['read1','read2'] # def read(): # print('in read1',money) # # def read2(): # print('in read2')
# from 模块名 import * 和 __all__ 是一对
# 没有这个变量,就会导入所有的名字
# 如果有all 只导入all列表中的名字
将模块当做脚本来运行
if __name__ == "__main__": main()
我们可以通过模块的全局变量__name__来查看模块名:
当做脚本运行:
__name__ 等于'__main__'
当做模块导入:
__name__= 模块名
作用:用来控制.py文件在不同的应用场景下执行不同的逻辑
if __name__ == '__main__':
举一个例子来说明一下,假设我们有一个 const.py 文件,内容如下:
PI = 3.14 def main(): print "PI:", PI main()
我们在这个文件里边定义了一些常量,然后又写了一个 main 函数来输出定义的常量,最后运行 main 函数就相当于对定义做一遍人工检查,看看值设置的都对不对。
然后我们直接执行该文件(python const.py),输出:
PI: 3.14
现在,我们有一个 area.py 文件,用于计算圆的面积,该文件里边需要用到 const.py 文件中的 PI 变量,那么我们从 const.py 中把 PI 变量导入到 area.py 中:
from const import PI def calc_round_area(radius): return PI * (radius ** 2) def main(): print "round area: ", calc_round_area(2) main()
运行 area.py,输出结果:
PI: 3.14
round area: 12.56
可以看到,const 中的 main 函数也被运行了,实际上我们是不希望它被运行,提供 main 也只是为了对常量定义进行下测试。这时,if __name__ == '__main__'
就派上了用场。把 const.py 改一下:
PI = 3.14 def main(): print "PI:", PI if __name__ == "__main__": main()
然后再运行 area.py,输出如下:
round area: 12.56
再运行下 const.py,输出如下:
PI: 3.14
这才是我们想要的效果。
所以,if __name__ == '__main__'
我们简单的理解就是: 如果模块是被直接运行的,则代码块被运行,如果模块是被导入的,则代码块不被运行。
包
1. 无论是import形式还是from...import形式,凡是在导入语句中(而不是在使用时)遇到带点的,都要第一时间提高警觉:这是关于包才有的导入语法
2. 包是目录级的(文件夹级),文件夹是用来组成py文件(包的本质就是一个包含__init__.py文件的目录)
3. import导入文件时,产生名称空间中的名字来源于文件,import 包,产生的名称空间的名字同样来源于文件,即包下的__init__.py,导入包本质就是在导入该文件,且导入过程是在__init__.py文件下执行的
强调:
1. 在python3中,即使包下没有__init__.py文件,import 包仍然不会报错,而在python2中,包下一定要有该文件,否则import 包报错
2. 创建包的目的不是为了运行,而是被导入使用,记住,包只是模块的一种形式而已,包即模块
包相关的导入语句也分为import和from ... import ...两种
import
这里的导入模式可以是包+模块,但是最小的单位也只能是模块而不能是变量或者是函数,如果我们想直接使用变量或者函数那必须使用后者。
import 包,模块 #此时如果想要调用函数或者变量需要 模块.函数()
from .......import ...
需要注意的是from后import导入的模块,必须是明确的一个不能带点,否则会有语法错误,如:from a import b.c是错误语法
# from a.b import c # c.main('haha') # from a.b.d import main # main('haha')