模块
什么是模块?
常见的场景:一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀。
但其实import加载的模块分为四个通用类别:
1 使用python编写的代码(.py文件)
2 已被编译为共享库或DLL的C或C++扩展
3 包好一组模块的包
4 使用C编写并链接到python解释器的内置模块
为何要用模块?
如果你退出python解释器然后重新进入,那么你之前定义的函数或者变量都将丢失,因此我们通常将程序写到文件中以便永久保存下来,需要时就通过python test.py方式去执行,此时test.py被称为脚本script。
随着程序的发展,功能越来越多,为了方便管理,我们通常将程序分成一个个的文件,这样做程序的结构更清晰,方便管理。这时我们不仅仅可以把这些文件当做脚本去执行,还可以把他们当做模块来导入到其他的模块中,实现了功能的重复利用,
序列化模块
什么叫做序列化---将原本的字典,列表等内容转换成一个字符串的过程就叫做序列化
比如,我们在python代码中计算的一个数据需要给另外一段程序使用,那我们怎么给? 现在我们能想到的方法就是存在文件里,然后另一个python程序再从文件里读出来。 但是我们都知道,对于文件来说是没有字典这个概念的,所以我们只能将数据转换成字典放到文件中。 你一定会问,将字典转换成一个字符串很简单,就是str(dic)就可以办到了,为什么我们还要学习序列化模块呢? 没错序列化的过程就是从dic 变成str(dic)的过程。现在你可以通过str(dic),将一个名为dic的字典转换成一个字符串, 但是你要怎么把一个字符串转换成字典呢? 聪明的你肯定想到了eval(),如果我们将一个字符串类型的字典str_dic传给eval,就会得到一个返回的字典类型了。 eval()函数十分强大,但是eval是做什么的?e官方demo解释为:将字符串str当成有效的表达式来求值并返回计算结果。 BUT!强大的函数有代价。安全性是其最大的缺点。 想象一下,如果我们从文件中读出的不是一个数据结构,而是一句"删除文件"类似的破坏性语句,那么后果实在不堪设设想。 而使用eval就要担这个风险。 所以,我们并不推荐用eval方法来进行反序列化操作(将str转换成python中的数据结构)
序列化的目的
1,以某种存储形式使自定义对象持久化
2,将对象从一个地方传递到另一个地方
3,是程序更具维护性.

json
json模块提供了四个功能:dunps,dump,loads,load
import json dic = {"k1": "v1", "k2": "v2", "k3": "v3"} str_dic = json.dumps(dic) # 序列化:将一个字典转换成一个字符串 print(type(str_dic), str_dic) # <class 'str'> {"k1": "v1", "k2": "v2", "k3": "v3"} # 注意: json转换完的字符串类型的字典中的字符串是由""表示的 dic2 = json.loads(str_dic) # 反序列化 # 注意: 要用json的loads功能处理的字符串类型的字典中的字符串必须由""表示 print(type(dic2), dic2) # <class 'dict'> {'k1': 'v1', 'k2': 'v2', 'k3': 'v3'} list_dic = [1, ['a', 'b', 'c'], 3, {'k1': 'v1', 'k2': 'v2'}] str_dic1 = json.dumps(list_dic) print(type(str_dic1), str_dic1) list_dic2 = json.loads(str_dic1) print(list_dic2, type(list_dic2)) # 也可以处理嵌套数据类型
import json f = open('json_file','w') dic = {'k1': 'v1', 'k2': 'v2', 'k3': 'v3'} json.dump(dic, f) # dump方法接受一个文件句柄,直接将字典转换成json字符串写入文件 f.close() f = open('json_file') dic2 = json.load(f) # load 方法接受一个文件句柄,直接将文件中的json字符串转换成数据结构返回 f.close() print(type(dic2), dic2)
import json f = open("file", 'w', encoding='utf-8') json.dump({"名字": "中国"}, f, ensure_ascii=False) ret = json.dumps({"名字": "中国"}, ensure_ascii=False) f.write(ret + '\n') json.dump({"名字": "陈润"}, f, ensure_ascii=False) ret = json.dumps({"名字": "陈润"}, ensure_ascii=False) f.write(ret + '\n') f.close()
Serialize obj to a JSON formatted str.(字符串表示的json对象) Skipkeys:默认值是False,如果dict的keys内的数据不是python的基本类型(str,unicode,int,long,float,bool,None),设置为False时,就会报TypeError的错误。此时设置成True,则会跳过这类key ensure_ascii:,当它为True的时候,所有非ASCII码字符显示为\uXXXX序列,只需在dump时将ensure_ascii设置为False即可,此时存入json的中文即可正常显示。) If check_circular is false, then the circular reference check for container types will be skipped and a circular reference will result in an OverflowError (or worse). If allow_nan is false, then it will be a ValueError to serialize out of range float values (nan, inf, -inf) in strict compliance of the JSON specification, instead of using the JavaScript equivalents (NaN, Infinity, -Infinity). indent:应该是一个非负的整型,如果是0就是顶格分行显示,如果为空就是一行最紧凑显示,否则会换行且按照indent的数值显示前面的空白分行显示,这样打印出来的json数据也叫pretty-printed json separators:分隔符,实际上是(item_separator, dict_separator)的一个元组,默认的就是(‘,’,’:’);这表示dictionary内keys之间用“,”隔开,而KEY和value之间用“:”隔开。 default(obj) is a function that should return a serializable version of obj or raise TypeError. The default simply raises TypeError. sort_keys:将数据根据keys的值进行排序。 To use a custom JSONEncoder subclass (e.g. one that overrides the .default() method to serialize additional types), specify it with the cls kwarg; otherwise JSONEncoder is used.
import json data = {'username':['李华','二愣子'],'sex':'male','age':16} json_dic2 = json.dumps(data,sort_keys=True,indent=2,separators=(',',':'),ensure_ascii=False) print(json_dic2)
利用json写入多个字典
dic = {'username': 'alex123', 'password': 123}
dic1 = {'username1': 'alex123', 'password': 123}
dic2 = {'username2': 'alex123', 'password': 123}
import json
with open("json_all", "w", encoding='utf-8') as f:
ret = json.dumps(dic)
f.write(ret+'\n')
ret1 = json.dumps(dic1)
f.write(ret1+'\n')
ret2 = json.dumps(dic2)
f.write(ret2+'\n')
f = open("json_all", encoding='utf-8')
for line in f:
ret = json.loads(line)
print(ret)
pickle
json & pickle
用于序列化的两个模块
json,用于字符串和python数据类型间进行转换
pickle,用于python特有的类型和python的数据类型间进行转换
pickle模块提供了四个功能:dumps,dump(序列化, 存), loads(反序列化,读),load(不仅可以序列化字典,列表..可以把python中的任意的数据类型序列化)
import pickle dic = {'k1':'v1','k2':'v2','k3':'v3'} str_dic = pickle.dumps(dic) print(str_dic) # 遗传位进制内容 dic2 = pickle.loads(str_dic) print(dic2) # 字典 import time struct_time = time.localtime(10000000) print(struct_time) f = open('pickle_file', 'wb') pickle.dump(struct_time, f) f.close() f = open('pickle_file', 'rb') struct_time2 = pickle.load(f) print(struct_time2.tm_year)
利用pickle写入多个字典到文件中
dic = {'username': 'alex123', 'password': 123}
dic1 = {'username1': 'alex123', 'password': 123}
dic2 = {'username2': 'alex123', 'password': 123}
import pickle
with open("pickle_file", "wb") as w:
pickle.dump(dic, w)
pickle.dump(dic1, w)
pickle.dump(dic2, w)
with open("pickle_file", "rb") as f:
while True:
try:
ret = pickle.load(f)
print(ret)
except EOFError:
break
这时候机智的你又要说了,既然pickle如此强大,为什么还要学json呢?
这里我们要说明一下,json是一种所有的语言都可以识别的数据结构。
如果我们将一个字典或者序列化成了一个json存在文件里,那么java代码或者js代码也可以拿来用。
但是如果我们用pickle进行序列化,其他语言就不能读懂这是什么了~
所以,如果你序列化的内容是列表或者字典,我们非常推荐你使用json模块
但如果出于某种原因你不得不序列化其他的数据类型,而未来你还会用python对这个数据进行反序列化的话,那么就可以使用pickle
shelve
shelve也是python提供给我们的序列化工具,比pickle用起来更简单一些。
shelve只提供给我们一个open方法,是用key来访问的,使用起来和字典类似。
import shelve f = shelve.open('shelve_file') f['key'] = {'int':10, 'float':9.5, 'string':'Sample data'} #直接对文件句柄操作,就可以存入数据 f.close() import shelve f1 = shelve.open('shelve_file') existing = f1['key'] #取出数据的时候也只需要直接用key获取即可,但是如果key不存在会报错 f1.close() print(existing) shelve
这个模块有个限制,它不支持多个应用同一时间往同一个DB进行写操作。所以当我们知道我们的应用如果只进行读操作,我们可以让shelve通过只读方式打开DB
import shelve f = shelve.open('shelve_file', flag='r') existing = f['key'] f.close() print(existing)
由于shelve在默认情况下是不会记录待持久化对象的任何修改的,所以我们在shelve.open()时候需要修改默认参数,否则对象的修改不会保存。
import shelve f1 = shelve.open('shelve_file') print(f1['key']) f1['key']['new_value'] = 'this was not here before' f1.close() f2 = shelve.open('shelve_file', writeback=True) print(f2['key']) f2['key']['new_value'] = 'this was not here before' f2.close()
writeback方式有优点也有缺点。优点是减少了我们出错的概率,并且让对象的持久化对用户更加的透明了;但这种方式并不是所有的情况下都需要,首先,使用writeback以后,shelf在open()的时候会增加额外的内存消耗,并且当DB在close()的时候会将缓存中的每一个对象都写入到DB,这也会带来额外的等待时间。因为shelve没有办法知道缓存中哪些对象修改了,哪些对象没有修改,因此所有的对象都会被写入。
hashlib模块
算法介绍
Python的hashlib提供了常见的摘要算法,如MD5,SHA1等等。
什么是摘要算法呢?摘要算法又称哈希算法、散列算法。它通过一个函数,把任意长度的数据转换为一个长度固定的数据串(通常用16进制的字符串表示)。
摘要算法就是通过摘要函数f()对任意长度的数据data计算出固定长度的摘要digest,目的是为了发现原始数据是否被人篡改过。
摘要算法之所以能指出数据是否被篡改过,就是因为摘要函数是一个单向函数,计算f(data)很容易,但通过digest反推data却非常困难。而且,对原始数据做一个bit的修改,都会导致计算出的摘要完全不同。
我们以常见的摘要算法MD5为例,计算出一个字符串的MD5值:
import hashlib str = "12345678" str1 = str.encode("utf-8") ret = hashlib.md5() ret.update(str1) print(ret.hexdigest())
如果数据量很大,可以分块多次调用update(),最后的计算结果一样的:
ret = hashlib.md5() ret.update("123".encode("utf-8")) ret.update("45678".encode("utf-8")) print(ret.hexdigest())
MD5是最常见的摘要算法,速度很快,生成结果是固定的128bit字节,通常用一个32位的16进制字符串表示,另一种常见的摘要算法是SHA1,调用SHA1和调用MD5完全类似
import hashlib sha1 = hashlib.sha1() sha1.update("123456".encode("utf-8")) print(sha1.hexdigest()) # 7c4a8d09ca3762af61e59520943dc26494f8941b
SHA1的结果是160bit字节,通常是一个40位的16位进制字符串表示,比ShA1更安全的算法是SHA256和SHA512,不过越安全的算法越慢,而且摘要长的更长
摘要算法应用
任何允许用户登陆的网站都会存储用户登陆的用户名和口令,如果存储用户名和口令呢?方法是存到数据库表中
name | password --------+---------- michael | 123456 bob | abc999 alice | alice2008
如果以明文保存用户口令,如果数据库泄露,所有用户的口令就落入黑客的手里。此外,网站运维人员是可以访问数据库的,也就是能获取到所有用户的口令。正确的保存口令的方式是不存储用户的明文口令,而是存储用户口令的摘要,比如MD5:
username | password ---------+--------------------------------- michael | e10adc3949ba59abbe56e057f20f883e bob | 878ef96e86145580c38c87f0410ad153 alice | 99b1c2188db85afee403b1536010c2c9
考虑这么个情况,很多用户喜欢用123456,888888,password这些简单的口令,于是,黑客可以事先计算出这些常用口令的MD5值,得到一个反推表:
'e10adc3949ba59abbe56e057f20f883e': '123456' '21218cca77804d2ba1922c33e0151105': '888888' '5f4dcc3b5aa765d61d8327deb882cf99': 'password'
这样,无需破解,只需要对比数据库的MD5,黑客就获得了使用常用口令的用户账号。
对于用户来讲,当然不要使用过于简单的口令。但是,我们能否在程序设计上对简单口令加强保护呢?
由于常用口令的MD5值很容易被计算出来,所以,要确保存储的用户口令不是那些已经被计算出来的常用口令的MD5,这一方法通过对原始口令加一个复杂字符串来实现,俗称“加盐”:
hashlib.md5("salt".encode("utf-8"))
经过Salt处理的MD5口令,只要Salt不被黑客知道,即使用户输入简单口令,也很难通过MD5反推明文口令。
但是如果有两个用户都使用了相同的简单口令比如123456,在数据库中,将存储两条相同的MD5值,这说明这两个用户的口令是一样的。有没有办法让使用相同口令的用户存储不同的MD5呢?
如果假定用户无法修改登录名,就可以通过把登录名作为Salt的一部分来计算MD5,从而实现相同口令的用户也存储不同的MD5。
摘要算法在很多地方都有广泛的应用。要注意摘要算法不是加密算法,不能用于加密(因为无法通过摘要反推明文),只能用于防篡改,但是它的单向计算特性决定了可以在不存储明文口令的情况下验证用户口令。
configparser模块
该模块适用于配置文件的格式与windows ini文件类似,可以包含一个或多个节(section),每个节可以有多个参数(键=值)。
创建文件
来看一下好多软件的常见文档格式如下:
[DEFAULT] ServerAliveInterval = 45 Compression = yes CompressionLevel = 9 ForwardX11 = yes [bitbucket.org] User = hg [topsecret.server.com] Port = 50022 ForwardX11 = no
如果想用python生成一个这样的文档怎么做呢?
import configparser config = configparser.ConfigParser() config["DEFAULT"] = {'ServerAliveInterval': '45', 'Compression': 'yes', 'CompressionLevel': '9', 'ForwardX11':'yes' } config['bitbucket.org'] = {'User':'hg'} config['topsecret.server.com'] = {'Host Port':'50022','ForwardX11':'no'} with open('example.ini', 'w') as configfile: config.write(configfile)
查找文件
import configparser config = configparser.ConfigParser() #---------------------------查找文件内容,基于字典的形式 print(config.sections()) # [] config.read('example.ini') print(config.sections()) # ['bitbucket.org', 'topsecret.server.com'] print('bytebong.com' in config) # False print('bitbucket.org' in config) # True print(config['bitbucket.org']["user"]) # hg print(config['DEFAULT']['Compression']) #yes print(config['topsecret.server.com']['ForwardX11']) #no print(config['bitbucket.org']) #<Section: bitbucket.org> for key in config['bitbucket.org']: # 注意,有default会默认default的键 print(key) print(config.options('bitbucket.org')) # 同for循环,找到'bitbucket.org'下所有键 print(config.items('bitbucket.org')) #找到'bitbucket.org'下所有键值对 print(config.get('bitbucket.org','compression')) # yes get方法Section下的key对应的value
增删改操作
import configparser config = configparser.ConfigParser() config.read('example.ini') config.add_section('yuan') config.remove_section('bitbucket.org') config.remove_option('topsecret.server.com',"forwardx11") config.set('topsecret.server.com','k1','11111') config.set('yuan','k2','22222') config.write(open('new2.ini', "w"))
logging模块
函数是简单配置
import logging logging.debug("debug message") logging.info("info message") logging.warning("warning message") logging.error("error message") logging.critical("critical message")
默认情况下python的logging模块将日志打印到了标准输出中,且显示大于等于warning级别的日志,这说明默认的日志级别设置位warning(日志级别等级critical>error>warning>info>debug),默认的日志格式为日志级别:logger名称:用户输出消息
import logging 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='test.log', filemode='w') logging.debug("debug message") logging.info("info message") logging.warning("warning message") logging.error('error message') logging.critical('critical message')
logging.basicConfig()函数可以通过具体参数来更改logging模块默认行为,可用参数有: filename: 用指定的文件名创建FiledHandler,这样日志会被存储在指定的文件中 filemode: 文件打开方式,在指定了filename时使用这个参数,默认为"a"还可以指定为"w" format: 指定handler使用的日志显示格式 datefmt: 指定日期时间格式 level:设置rootlogger(后面还有具体概念)的日志级别 stream: 用指定的stream创建StreamHandler.可以指定输出sys.stder, sys.stdout或者文件 (f = open('test.log', 'w')),默认为sys.stderr.若同时列出了filename和stream两个参数,则stram参数别忽略 format参数中可能用到的格式化串: % (name)s Logger的名字 %(levelno)s 数字形式的日志级别 %(pathname)s 调用日志输出函数的模块的完整路径名,可能没有 %(levelname)s 文本形式的日志级别 %(filename)s 调用日志输出函数的模块的文件名 %(module)s 调用日志输出函数的模块名 %(funcName)s 调用日志输出函数的函数名 %(lineno)d 调用日志输出函数的语句所在的代码行 %(created)f 当前时间,用unix标准的表示时间的浮点数表示 %(relativeCreated)d 输出日志信息是的,自logger创建以来的毫秒数 %(asctime)s 字符串形式的当前时间.默认格式是:"2018-07-08 16:59:40,455".逗号后面的是毫秒 %(threadName)s 线程名.可能没有 %(thread)d 线程id ,可能没有 %(process)d 进程id, 可能没有 %(message)s 用户输出的消息
logger对象配置
import logging logger = logging.getLogger() # 创建一个handler,用于写入日志文件 fh = logging.FileHandler('test1.log', encoding='utf-8') # 再创建一个handler,用于输出控制台的内容 ch = logging.StreamHandler() formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") fh.setLevel(logging.DEBUG) fh.setFormatter(formatter) ch.setFormatter(formatter) logger.addHandler(fh) # logger对象可以添加多个fh和ch对象 logger.addHandler(ch) logger.debug('logger debug message') logger.info('logger info message') logger.warning('logger warning message') logger.error('logger error message') logger.critical('logger critical message')
logging库提供了多个组件:Logger,Handler,Filter,Formatter.Logger对象提供应用程序可直接使用的接口,Handler发送日志到适当的目的,Filter提供了过滤日志信息的方法,Formatter指定日志显示格式.另外,可以通过:logger.setLevel(logging.Debug)设置级别,当然也可以通过
fh.setLevel(logging.Debug)但对文件流设置某个级别.
完整版
import logging logger = logging.getLogger() # 创建logger对象 # 创建控制台和文件对象 fh = logging.FileHandler("logger_fh.log", encoding='utf-8') sh = logging.StreamHandler() # 设定格式 formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") # 设定等级 logger.setLevel(logging.DEBUG) # 总格式 # 接受控制台和文件对象 logger.addHandler(fh) logger.addHandler(sh) sh.setFormatter(formatter) # 将屏幕规定为设定的格式 fh.setFormatter(formatter) sh.setLevel(logging.INFO) # 屏幕的等级 logging.debug("debug message") logging.info("info message") logging.warning("warning message") logging.error("error message") logging.critical("critical message")
collection模块
在内置数据类型(dict,list,set,tuple)的基础上,collection模块提供了几个额外的数据类型: Counter,depue,defaultdict,namedtuple和OrdereDict等
1,namedtuple: 生成可以使用名字来访问元素内容的tuple
2,depue: 双端队列,可以快速的从另外一侧追加和推出对象
3,Counter: 计数器,主要用来计数
4,OrdereDict: 有序字典
5,defaultdict:带有默认值的字典
namedtuple
我们知道tuple可以表示不变集合,例如,一个点的二维坐标就可以表示成:
p = (1, 2)
但是,看到(1,2),很难看出这个tuple用来表示一个坐标
这是namedtuple就派上了用场
from collections import namedtuple point = namedtuple('point', ['x', 'y']) p = point(1, 2) print(p.x) print(p.y)
类似的,如果用坐标和半径表示一个圆,也可以用namedtuple定义:
# namedtuple("名称", [属性list]) Circle = namedtuple("Circle", ['x', 'y', 'r'])
depue
使用list存储数据是,按索引访问元素很快,但是插入和删除元素就很慢了,因为list是线性存储,数据量大的时候,插入和删除效率很低
depue是为了高效率插入和删除操作的双向列表,适合用于队列和栈:
from collections import deque q = deque(['a', 'b', 'c']) q.append('x') q.appendleft('y') print(q) #deque(['y', 'a', 'b', 'c', 'x'])
deque除了实现list的append()和pop()外,还支持appendleft()和popleft(),这样就可以非常高效地往头部添加或删除元素
OrderedDict
使用dict时,Key是无序的,在对dict做迭代时,我们无法确定key顺序.
如果要保持key的顺序,可以用OrderedDict
>>> from collections import OrderedDict >>> d = dict([('a', 1), ('b', 2), ('c', 3)]) >>> d # dict的Key是无序的 {'a': 1, 'c': 3, 'b': 2} >>> od = OrderedDict([('a', 1), ('b', 2), ('c', 3)]) >>> od # OrderedDict的Key是有序的 OrderedDict([('a', 1), ('b', 2), ('c', 3)])
注意: OrderedDict的key会按照插入的顺序排序,不是key本身排序
>>> od = OrderedDict() >>> od['z'] = 1 >>> od['y'] = 2 >>> od['x'] = 3 >>> od.keys() # 按照插入的Key的顺序返回 ['z', 'y', 'x']
defaultdict
有如下值集合[11,22,33,44,55,66,77,88,99,90......],将所有大于66的值保存至字典的第一个key中,将小于66的值保存至第二个key中
from collections import defaultdict values = [11, 22, 33, 44, 55, 66, 77, 88, 99, 90] my_dict = defaultdict(list) for value in values: if value > 66: my_dict['k1'].append(value) else: my_dict['k2'].append(value) print(my_dict)
使用dict时,如果引用的key不存在,就会抛出KeyError.如果希望key不存在时,返回一个默认值,就可以用defaultdict:
from collections import defaultdict d = defaultdict(lambda: 'N/A') d['key1'] = 'abc' print(d['key1']) print(d['key2']) # abc # N/A
counter
Counter类的目的是用来跟踪值出现的次数,他是一个无序的容器类型,以字典的键值对形式存储,其中元素作为key,其计数作为value.计数值可以时任意的interger(包括0和负数).Counter类和其他语言的bags或multisets很类似
c = Counter('abcdefabcdefabcdefabcdef) print(c)
时间模块
和时间有关系的我们就要用到时间模块.在使用模块之前,应该首先导入这个模块
import time # 常用方法 time.sleep(2) # (线程)推迟指定的时间运行.单位为秒 a = time.time() # 获取时间戳
表示时间的三种方式
在python中,通常由这三种方式来表示时间,时间戳,元组(struct_time),格式化时间字符串:
(1)时间戳:通常来说,时间戳表示的时从1970年1月1日00:00:00开始按秒计算的偏移量.我们运行"type(time.time())",返回的时float类型
(2),格式化的时间字符串(Format string): "1999 - 12 - 06"
%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 当前时区的名称 %% %号本身 python中时间日期格式化符号:
(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 a = time.time() print(a) # 1531099458.5932288 b = time.strftime("%Y-%m-%d %x") print(b) # 2018-07-09 07/09/18 c = time.strftime("%Y-%m-%d %H-%M-%S") print(c) # 2018-07-09 09-25-17 # 时间元组: localtime将一个时间戳转换为当前时区的struct_time
小结: 世家戳是计算能够识别的时间;时间字符串时人能够看懂的时间;元组则是用来操作时间的
几种格式之间的转换

#时间戳-->结构化时间 #time.gmtime(时间戳) #UTC时间,与英国伦敦当地时间一致 #time.localtime(时间戳) #当地时间。例如我们现在在北京执行这个方法:与UTC时间相差8小时,UTC时间+8小时 = 北京时间 >>>time.gmtime(1500000000) time.struct_time(tm_year=2017, tm_mon=7, tm_mday=14, tm_hour=2, tm_min=40, tm_sec=0, tm_wday=4, tm_yday=195, tm_isdst=0) >>>time.localtime(1500000000) time.struct_time(tm_year=2017, tm_mon=7, tm_mday=14, tm_hour=10, tm_min=40, tm_sec=0, tm_wday=4, tm_yday=195, tm_isdst=0) #结构化时间-->时间戳 #time.mktime(结构化时间) >>>time_tuple = time.localtime(1500000000) >>>time.mktime(time_tuple) 1500000000.0
#结构化时间-->字符串时间 #time.strftime("格式定义","结构化时间") 结构化时间参数若不传,则现实当前时间 >>>time.strftime("%Y-%m-%d %X") '2017-07-24 14:55:36' >>>time.strftime("%Y-%m-%d",time.localtime(1500000000)) '2017-07-14' #字符串时间-->结构化时间 #time.strptime(时间字符串,字符串对应格式) >>>time.strptime("2017-03-16","%Y-%m-%d") time.struct_time(tm_year=2017, tm_mon=3, tm_mday=16, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=75, tm_isdst=-1) >>>time.strptime("07/24/2017","%m/%d/%Y") time.struct_time(tm_year=2017, tm_mon=7, tm_mday=24, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=0, tm_yday=205, tm_isdst=-1)

#结构化时间 --> %a %b %d %H:%M:%S %Y串 #time.asctime(结构化时间) 如果不传参数,直接返回当前时间的格式化串 >>>time.asctime(time.localtime(1500000000)) 'Fri Jul 14 10:40:00 2017' >>>time.asctime() 'Mon Jul 24 15:18:33 2017' #时间戳 --> %a %d %d %H:%M:%S %Y串 #time.ctime(时间戳) 如果不传参数,直接返回当前时间的格式化串 >>>time.ctime() 'Mon Jul 24 15:19:07 2017' >>>time.ctime(1500000000) 'Fri Jul 14 10:40:00 2017'
import time true_time=time.mktime(time.strptime('2017-09-11 08:30:00','%Y-%m-%d %H:%M:%S')) time_now=time.mktime(time.strptime('2017-09-12 11:00:00','%Y-%m-%d %H:%M:%S')) dif_time=time_now-true_time struct_time=time.gmtime(dif_time) print('过去了%d年%d月%d天%d小时%d分钟%d秒'%(struct_time.tm_year-1970,struct_time.tm_mon-1, struct_time.tm_mday-1,struct_time.tm_hour, struct_time.tm_min,struct_time.tm_sec))
random模块
>>> import random #随机小数 >>> random.random() # 大于0且小于1之间的小数 0.7664338663654585 >>> random.uniform(1,3) #大于1小于3的小数 1.6270147180533838 #恒富:发红包 #随机整数 >>> 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,3,5,7,9] >>> random.shuffle(item) # 打乱次序 >>> item [5, 1, 3, 7, 9] >>> random.shuffle(item) >>> item [5, 9, 7, 1, 3]
import random def code(): code_c = '' for item in range(5): num = random.randint(0,9) alf = chr(random.randint(65, 90)) add = random.choice([num,alf]) code_c = ''.join([code_c, str(add)]) return code_c print(code())
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下为"\t\n",Linux下为"\n" 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')获取文件/目录信息的结构说明
stat 结构: 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)是创建时间(详细信息参见平台的文档)。
os模块计算文件大小
import os def get_filesize(filePath, size=0): for root, dirs, files in os.walk(filePath): print(root) print(dirs) print(files) for f in files: size += os.path.getsize(os.path.join(root, f)) print(f) return size print(get_filesize("D:\数据管理\python全栈开发13期\网络编程\day_39\计算文件大小"))
sys模块
sys模块是与python解释器交互的一个接口
sys.argv 命令行参数List,第一个元素是程序本身路径 sys.exit(n) 退出程序,正常退出时exit(0),错误退出sys.exit(1) sys.version 获取Python解释程序的版本信息 sys.path 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值 sys.platform 返回操作系统平台名称
import sys try: sys.exit(1) except SystemExit as e: print(e)

浙公网安备 33010602011771号