Python基础(11)_python模块之time模块、rando模块、hashlib、os模块
一、模块
1、什么是模块:一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀
模块的本质:模块的本质是一个py文件
2、模块分为三类:1)内置模块;2)第三方模块;3)自定义模块
3、使用模块的目的:
退出python解释器然后重新进入,那么你之前定义的函数或者变量都将丢失,因此我们通常将程序写到文件中以便永久保存下来,需要时就通过python test.py方式去执行,此时test.py被称为脚本script。
随着程序的发展,功能越来越多,为了方便管理,我们通常将程序分成一个个的文件,这样做程序的结构更清晰,方便管理。这时我们不仅仅可以把这些文件当做脚本去执行,还可以把他们当做模块来导入到其他的模块中,实现了功能的重复利用,
4、模块的使用:通过import 调用
示例文件:spam.py,文件名spam.py,模块名spam
1 #spam.py 2 print('from the spam.py') 3 4 money=1000 5 6 def read1(): 7 print('spam->read1->money',money) 8 9 def read2(): 10 print('spam->read2 calling read') 11 read1() 12 13 def change(): 14 global money 15 money=0
4.1模块可以包含可执行的语句和函数的定义,这些语句的目的是初始化模块,它们只在模块名第一次遇到导入import语句时才执行(import语句是可以在程序中的任意位置使用的,且针对同一个模块很import多次,为了防止你重复导入,python的优化手段是:第一次导入后就将模块名加载到内存了,后续的import语句仅是对已经加载大内存中的模块对象增加了一次引用,不会重新执行模块内的语句),如下
1 #test.py 2 import spam #只在第一次导入时才执行spam.py内代码,此处的显式效果是只打印一次'from the spam.py',当然其他的顶级代码也都被执行了,只不过没有显示效果. 3 import spam 4 import spam 5 import spam 6 7 ''' 8 执行结果: 9 from the spam.py 10 '''
我们可以从sys.module中找到当前已经加载的模块,sys.module是一个字典,内部包含模块名与模块对象的映射,该字典决定了导入模块时是否需要重新导入。
4.2 每个模块都是一个独立的名称空间,定义在这个模块中的函数,把这个模块的名称空间当做全局名称空间,这样我们在编写自己的模块时,就不用担心我们定义在自己模块中全局变量会在被导入时,与使用者的全局变量冲突
1 #测试一:money与spam.money不冲突 2 #test.py 3 import spam 4 money=10 5 print(spam.money) 6 7 ''' 8 执行结果: 9 from the spam.py 10 1000 11 '''
1 #测试二:read1与spam.read1不冲突 2 #test.py 3 import spam 4 def read1(): 5 print('========') 6 spam.read1() 7 8 ''' 9 执行结果: 10 from the spam.py 11 spam->read1->money 1000 12 '''
1 #测试三:执行spam.change()操作的全局变量money仍然是spam中的 2 #test.py 3 import spam 4 money=1 5 spam.change() 6 print(money) 7 8 ''' 9 执行结果: 10 from the spam.py 11 1 12 '''
总结:首次导入模块spam时会做三件事:
1.为源文件(spam模块)创建新的名称空间,在spam中定义的函数和方法若是使用到了global时访问的就是这个名称空间。
2.在新创建的命名空间中执行模块中包含的代码,见初始导入import spam
3.创建名字spam来引用该命名空间
1.#为模块名起别名,相当于m1=1;m2=m1 2.import spam as sm 3.print(sm.money) #在一行导入多个模块 1.import sys,os,re
二、常用内置模块
1、time模块
1、时间的表示形式
在Python中,通常有这三种方式来表示时间:时间戳、元组(struct_time)、格式化的时间字符串:
(1)时间戳(timestamp) :通常来说,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量。我们运行“type(time.time())”,返回的是float类型。
(2)格式化的时间字符串(Format String): ‘1988-03-16’
(3)元组(struct_time) :struct_time元组共有9个元素共九个元素:(年,月,日,时,分,秒,一年中第几周,一年中第几天等)
1 # <1> 时间戳 2 >>> import time 3 >>> time.time() #--------------返回当前时间的时间戳 4 1493136727.099066 5 6 # <2> 时间字符串 7 >>> time.strftime("%Y-%m-%d %X") 8 '2017-04-26 00:32:18' 9 10 # <3> 时间元组 11 >>> time.localtime() 12 time.struct_time(tm_year=2017, tm_mon=4, tm_mday=26, 13 tm_hour=0, tm_min=32, tm_sec=42, tm_wday=2, 14 tm_yday=116, tm_isdst=0)
小结:时间戳是计算机能够识别的时间;时间字符串是人能够看懂的时间;元组则是用来操作时间的
附:python中时间日期格式化符号
python中时间日期格式化符号: %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 当前时区的名称 %% %号本身
2、几种时间形式的转换
(1)
1 # print(time.time()) # 仅仅是当前时间的时间戳 float型 2 #------------------------------------------------ 3 #print(time.localtime()) # 当前时间的结构化时间对象 4 5 s=time.localtime(312431212) # 结构化时间对象 将时间戳------->结构化时间 6 s2=time.gmtime() # 结构化时间对象 UTC时间 7 8 # print(s.tm_year) 9 # print(s.tm_wday) 10 #------------------------------------------------ 11 t="2012-12-12" 12 ret=time.mktime(time.localtime()) # 将结构化时间------->时间戳 13 print(ret) 14 #------------------------------------------------ 15 ret2=time.strftime("%Y-%m-%d",time.localtime()) # 将结构化时间------>字符串时间 16 print(ret2) 17 #------------------------------------------------ 18 ret3=time.strptime("1900:03:12","%Y:%m:%d") # 将字符串时间----->结构化时间 19 print(ret3)
(2)
1 >>> time.asctime(time.localtime(312343423)) 2 'Sun Nov 25 10:03:43 1979' 3 >>> time.ctime(312343423) 4 'Sun Nov 25 10:03:43 1979'
#--------------------------其他方法 # sleep(secs) # 线程推迟指定的时间运行,单位为秒。
2、random模块
1、random模块的使用
>>> import random >>> random.random() # 大于0且小于1之间的小数 0.7664338663654585 >>> random.randint(1,5) # 大于等于1且小于等于5之间的整数 >>> random.randrange(1,3) # 大于等于1且小于3之间的整数 >>> random.choice([1,'23',[4,5]]) # #1或者23或者[4,5] >>> random.sample([1,'23',[4,5]],2) # #列表元素任意2个组合 [[4, 5], '23'] >>> random.uniform(1,3) #大于1小于3的小数 1.6270147180533838 >>> item=[1,3,5,7,9] >>> random.shuffle(item) # 打乱次序 >>> item [5, 1, 3, 7, 9] >>> random.shuffle(item) >>> item [5, 9, 7, 1, 3]
2、random模块的应用:最近生成五位数的验证码
#练习: 随机生成五位数验证码
def valdate_code():
ret=""
for i in range(5):
num=random.randint(0,9)
alfa=chr(random.randint(97, 122))
alfa2=chr(random.randint(65, 90))
s=random.choice([str(num),alfa,alfa2])
ret=ret+s
return ret
# 思路2
# ret=random.sample([1,2,3,4,5,6,7,8,9,0],5)
# print(ret)
# print(type(ret))
# #
# ret=''.join(ret)
# # return ret
print(valdate_code())
3、hashlib
1、hash:一种摘要算法 ,3.x里代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法
2、摘要算法又称哈希算法、散列算法。它通过一个函数,把任意长度的数据转换为一个长度固定的数据串(通常用16进制的字符串表示)
三个特点:
1.内容相同则hash运算结果相同,内容稍微改变则hash值则变
2.不可逆推
3.相同算法:无论校验多长的数据,得到的哈希值长度固定。
3、以常见的摘要算法MD5为例,计算出一个字符串的MD5值:
import hashlib
md5 = hashlib.md5()
md5.update('how to use md5 in python hashlib?')
print md5.hexdigest()
计算结果如下:
d26a53750bc40b38b65a520292f69306
如果数据量很大,可以分块多次调用update(),最后计算的结果是一样的:
md5 = hashlib.md5() md5.update('how to use md5 in ') md5.update('python hashlib?') print md5.hexdigest()
MD5是最常见的摘要算法,速度很快,生成结果是固定的128 bit字节,通常用一个32位的16进制字符串表示。另一种常见的摘要算法是SHA1,调用SHA1和调用MD5完全类似:
import hashlib sha1 = hashlib.sha1() sha1.update('how to use sha1 in ') sha1.update('python hashlib?') print sha1.hexdigest()
SHA1的结果是160 bit字节,通常用一个40位的16进制字符串表示。比SHA1更安全的算法是SHA256和SHA512,不过越安全的算法越慢,而且摘要长度更长。
4、摘要算法应用
4.1网站存储用户登录的用户名和登录密码
username | password ---------+--------------------------------- michael | e10adc3949ba59abbe56e057f20f883e bob | 878ef96e86145580c38c87f0410ad153 alice | 99b1c2188db85afee403b1536010c2c9
4.2,防止网站数据泄露后,黑客“撞库”,对网站存储用户登录的用户名和登录密码进行“加盐”,即通过对原始口令加一个复杂字符串来实现
hashlib.md5("abc".encode("utf8"))
经过Salt处理的MD5口令,只要Salt不被黑客知道,即使用户输入简单口令,也很难通过MD5反推明文口令。
4、os模块
1、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 输出用于分割文件路径的字符串 win下为;,Linux下为:
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.path.getsize(path) 返回path的大小
'''
1 os路径处理 2 #方式一:推荐使用 3 import os 4 #具体应用 5 import os,sys 6 possible_topdir = os.path.normpath(os.path.join( 7 os.path.abspath(__file__), 8 os.pardir, #上一级 9 os.pardir, 10 os.pardir 11 )) 12 sys.path.insert(0,possible_topdir) 13 14 15 #方式二:不推荐使用 16 os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))