时间戳(timestamp):时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量。
| time_stamp = time.time() |
| print(time_stamp, type(time_stamp)) |
格式化的时间字符串(format string):格式化时间表示的是普通的字符串格式的时间。
| format_time = time.strftime("%Y-%m-%d %X") |
| print(format_time, type(format_time)) |
结构化的时间(struct time):struct_time元组共有9个元素共九个元素,分别为(年,月,日,时,分,秒,一年中第几周,一年中第几天,夏令时)
| print('本地时区的struct_time:\n{}'.format(time.localtime())) |
| print('UTC时区的struct_time:\n{}'.format(time.gmtime())) |
| 本地时区的struct_time: |
| time.struct_time(tm_year=2019, tm_mon=3, tm_mday=7, tm_hour=16, tm_min=22, tm_sec=11, tm_wday=3, tm_yday=66, tm_isdst=0) |
| UTC时区的struct_time: |
| time.struct_time(tm_year=2019, tm_mon=3, tm_mday=7, tm_hour=8, tm_min=22, tm_sec=11, tm_wday=3, tm_yday=66, tm_isdst=0) |
| time.struct_time(tm_year=1970, tm_mon=1, tm_mday=1, tm_hour=8, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=1, tm_isdst=0) |
| |
| print(time.localtime(3600*24*365)) |
| time.struct_time(tm_year=1971, tm_mon=1, tm_mday=1, tm_hour=8, tm_min=0, tm_sec=0, tm_wday=4, tm_yday=1, tm_isdst=0) |
如上图所示,我们总能通过某些方法在结构化时间-格式化时间-时间戳三者之间进行转换,下面我们将用代码展示如何通过这些方法转换时间格式。
| |
| now_time = time.localtime() |
| print(now_time) |
| time.struct_time(tm_year=2019, tm_mon=3, tm_mday=7, tm_hour=16, tm_min=22, tm_sec=11, tm_wday=3, tm_yday=66, tm_isdst=0) |
| |
| print(time.mktime(now_time)) |
| |
| |
| print(time.strftime("%Y-%m-%d %X", now_time)) |
| |
| print(time.strptime('2013-05-20 13:14:52', '%Y-%m-%d %X')) |
| time.struct_time(tm_year=2013, tm_mon=5, tm_mday=20, tm_hour=13, tm_min=14, tm_sec=52, tm_wday=0, tm_yday=140, tm_isdst=-1) |
| |
| print(time.asctime(time.localtime())) |
| |
| print(time.ctime(time.time())) |
| |
| start = time.time() |
| time.sleep(3) |
| end = time.time() |
| |
| print(end-start) |
| |
| print(datetime.datetime.now()) |
| 2019-03-07 16:22:14.544130 |
| print(datetime.date.fromtimestamp(time.time())) |
| |
| print(datetime.datetime.now() + datetime.timedelta(3)) |
| 2019-03-10 16:22:14.560599 |
| |
| print(datetime.datetime.now() + datetime.timedelta(-3)) |
| 2019-03-04 16:22:14.568473 |
| |
| print(datetime.datetime.now() + datetime.timedelta(hours=3)) |
| 2019-03-07 19:22:14.575881 |
| |
| print(datetime.datetime.now() + datetime.timedelta(minutes=30)) |
| 2019-03-07 16:52:14.585432 |
| |
| c_time = datetime.datetime.now() |
| print(c_time.replace(minute=20, hour=5, second=13)) |
| 2019-03-07 05:20:13.595493 |
| |
| print(random.randint(1, 3)) |
| |
| print(random.randrange(1, 3)) |
| |
| print(random.uniform(1, 3)) |
| |
| print(random.choice([1, '23', [4, 5]])) |
| |
| print(random.sample([1, '23', [4, 5]], 2)) |
| lis = [1, 3, 5, 7, 9] |
| |
| random.shuffle(lis) |
| print(lis) |
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的大小
sys模块负责程序与Python解释器进行交互。
方法 |
详解 |
sys.argv |
命令行参数List,第一个元素是程序本身路径 |
sys.modules.keys() |
返回所有已经导入的模块列表 |
sys.exc_info() |
获取当前正在处理的异常类,exc_type、exc_value、exc_traceback当前处理的异常详细信息 |
sys.exit(n) |
退出程序,正常退出时exit(0) |
sys.hexversion |
获取Python解释程序的版本值,16进制格式如:0x020403F0 |
sys.version |
获取Python解释程序的版本信息 |
sys.maxint |
最大的Int值 |
sys.maxunicode |
最大的Unicode值 |
sys.modules |
返回系统导入的模块字段,key是模块名,value是模块 |
sys.path |
返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值 |
sys.platform |
返回操作系统平台名称 |
sys.stdout |
标准输出 |
sys.stdin |
标准输入 |
sys.stderr |
错误输出 |
sys.exc_clear() |
用来清除当前线程所出现的当前的或最近的错误信息 |
sys.exec_prefix |
返回平台独立的python文件安装的位置 |
sys.byteorder |
本地字节规则的指示器,big-endian平台的值是’big’,little-endian平台的值是’little’ |
sys.copyright |
记录python版权相关的东西 |
sys.api_version |
解释器的C的API版本 |
把对象(变量)从内存中变成可存储或传输的过程称之为序列化,在Python中叫pickling,在其他语言中也被称之为serialization,marshalling,flattening。
序列化的优点:
- 持久保存状态:内存是无法永久保存数据的,当程序运行了一段时间,我们断电或者重启程序,内存中关于这个程序的之前一段时间的数据(有结构)都被清空了。但是在断电或重启程序之前将程序当前内存中所有的数据都保存下来(保存到文件中),以便于下次程序执行能够从文件中载入之前的数据,然后继续执行,这就是序列化。
- 跨平台数据交互:序列化时不仅可以把序列化后的内容写入磁盘,还可以通过网络传输到别的机器上,如果收发的双方约定好实用一种序列化的格式,那么便打破了平台/语言差异化带来的限制,实现了跨平台数据交互。
Json序列化并不是python独有的,json序列化在java等语言中也会涉及到,因此使用json序列化能够达到跨平台传输数据的目的。
json数据类型和python数据类型对应关系表
Json类型 |
Python类型 |
{} |
dict |
[] |
list |
"string" |
str |
520.13 |
int或float |
true/false |
True/False |
null |
None |
json模块序列化和反序列化的一个过程如下图所示
| struct_data = {'name': 'json', 'age': 23, 'sex': 'male'} |
| print(struct_data, type(struct_data)) |
| {'name': 'json', 'age': 23, 'sex': 'male'} |
| data = json.dumps(struct_data) |
| print(data, type(data)) |
| {"name": "json", "age": 23, "sex": "male"} |
| |
| data = json.loads(data) |
| print(data, type(data)) |
| {'name': 'json', 'age': 23, 'sex': 'male'} |
| |
| with open('Json序列化对象.json', 'w') as fw: |
| json.dump(struct_data, fw) |
| |
| with open('Json序列化对象.json') as fr: |
| data = json.load(fr) |
| print(data) |
| {'name': 'json', 'age': 23, 'sex': 'male'} |
Pickle序列化和所有其他编程语言特有的序列化问题一样,它只能用于Python,并且可能不同版本的Python彼此都不兼容,因此,只能用Pickle保存那些不重要的数据,即不能成功地反序列化也没关系。但是pickle的好处是可以存储Python中的所有的数据类型,包括对象,而json不可以。
pickle模块序列化和反序列化的过程如下图所示
| struct_data = {'name': 'json', 'age': 23, 'sex': 'male'} |
| print(struct_data, type(struct_data)) |
| {'name': 'json', 'age': 23, 'sex': 'male'} |
| data = pickle.dumps(struct_data) |
| print(data, type(data)) |
| b'\x80\x03}q\x00(X\x04\x00\x00\x00nameq\x01X\x04\x00\x00\x00jsonq\x02X\x03\x00\x00\x00ageq\x03K\x17X\x03\x00\x00\x00sexq\x04X\x04\x00\x00\x00maleq\x05u.' |
| data = pickle.loads(data) |
| print(data, type(data)) |
| {'name': 'json', 'age': 23, 'sex': 'male'} |
| |
| with open('Pickle序列化对象.pkl', 'wb') as fw: |
| pickle.dump(struct_data, fw) |
| |
| with open('Pickle序列化对象.pkl', 'rb') as fr: |
| pickle = pickle.load(fr) |
| print(data) |
| {'name': 'json', 'age': 23, 'sex': 'male'} |
hash是一种算法(Python3.版本里使用hashlib模块代替了md5模块和sha模块,主要提供 SHA1、SHA224、SHA256、SHA384、SHA512、MD5 算法),该算法接受传入的内容,经过运算得到一串hash值。
hash值的特点:
- 只要传入的内容一样,得到的hash值一样,可用于非明文密码传输时密码校验
- 不能由hash值返解成内容,即可以保证非明文密码的安全性
- 只要使用的hash算法不变,无论校验的内容有多大,得到的hash值长度是固定的,可以用于对文本的哈希处理
hash算法其实可以看成如下图所示的一座工厂,工厂接收你送来的原材料,经过加工返回的产品就是hash值
| m = hashlib.md5() |
| |
| m.update('hello'.encode('utf8')) |
| print(m.hexdigest()) |
| 5d41402abc4b2a76b9719d911017c592 |
| m.update('hash'.encode('utf8')) |
| print(m.hexdigest()) |
| 97fa850988687b8ceb12d773347f7712 |
| m2 = hashlib.md5() |
| m2.update('hellohash'.encode('utf8')) |
| print(m2.hexdigest()) |
| 97fa850988687b8ceb12d773347f7712 |
| m3 = hashlib.md5() |
| m3.update('hello'.encode('utf8')) |
| print(m3.hexdigest()) |
| 5d41402abc4b2a76b9719d911017c592 |
hash加密算法虽然看起来很厉害,但是他是存在一定缺陷的,即可以通过撞库可以反解,如下代码所示。
| import hashlib |
| |
| |
| pwd_list = [ |
| 'hash3714', |
| 'hash1313', |
| 'hash94139413', |
| 'hash123456', |
| '123456hash', |
| 'h123ash', |
| ] |
| |
| def make_pwd_dic(pwd_list): |
| dic = {} |
| for pwd in pwd_list: |
| m = hashlib.md5() |
| m.update(pwd.encode('utf-8')) |
| dic[pwd] = m.hexdigest() |
| return dic |
| |
| def break_code(hash_pwd, pwd_dic): |
| for k, v in pwd_dic.items(): |
| if v == hash_pwd: |
| print('hash的微信的密码是===>\033[46m%s\033[0m' % k) |
| |
| hash_pwd = '0562b36c3c5a3925dbe3c4d32a4f2ba2' |
| break_code(hash_pwd, make_pwd_dic(pwd_list)) |
| hash的微信的密码是===>[46mhash123456[0m |
为了防止密码被撞库,我们可以使用python中的另一个hmac 模块,它内部对我们创建key和内容做过某种处理后再加密。
如果要保证hmac模块最终结果一致,必须保证:
- hmac.new括号内指定的初始key一样
- 无论update多少次,校验的内容累加到一起是一样的内容
| import hmac |
| |
| |
| h1 = hmac.new(b'hash') |
| h1.update(b'hello') |
| h1.update(b'world') |
| print(h1.hexdigest()) |
| 905f549c5722b5850d602862c34a763e |
| h2 = hmac.new(b'hash') |
| h2.update(b'helloworld') |
| print(h2.hexdigest()) |
| 905f549c5722b5850d602862c34a763e |
| h3 = hmac.new(b'hashhelloworld') |
| print(h3.hexdigest()) |
| a7e524ade8ac5f7f33f3a39a8f63fd25 |