- time和datatime
- Range
- os
- sys
- hashlib
- XML
- json & picle
1、time和datetime
time和datetime都是python处理时间和日期的内置模块。
1.1 time模块
time模块中时间表现的方式主要有三种:
1、timestamp:时间戳,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量。
2、struct_time:时间元组,共有九个元素组。
3、format time :格式化时间,已格式化的结构使时间更具可读性。包括自定义格式和固定格式。
在python中直接获取看下:
import time # 直接获取timestamp >>> time.time() 1560409102.4841187 # 直接获取struct_time >>> time.localtime() time.struct_time(tm_year=2019, tm_mon=6, tm_mday=13, tm_hour=14, tm_min=59, tm_sec=0, tm_wday=3, tm_yday=164, tm_isdst=0) # 直接获取format time >>> time.strftime('%Y-%m-%d %X') '2019-06-13 15:01:35'
time模块主要通过6种方法进行时间格式的转换,看图:
1.1.1 时间戳和时间元组转换
>>> import time >>> t1 = time.time() # 获取时间戳并赋值 >>> time.localtime(t1) # 将时间戳转换为时间元组 time.struct_time(tm_year=2019, tm_mon=6, tm_mday=13, tm_hour=16, tm_min=25, tm_sec=14, tm_wday=3, tm_yday=164, tm_isdst=0) >>> t2 = time.localtime() # 获取时间元组并赋值 >>> time.mktime(t2) # 将时间元组转换为时间戳 1560414512.0
函数gmtime()的用法和localtime() 类似,localtime作用是格式化时间戳为本地的时间,gmtime()作用是格式化时间戳为格林尼治时间(世界标准时间UTC)。
1.1.2. 格式化时间和时间元组转换
time.strftime() 函数接收以时间元组,并返回以可读字符串表示的当地时间,格式由参数format决定;time.strptime() 函数接收以格式化时间,并返回时间元组,语法如下:
time.strftime(format,t1)
time.strptime(t2,format)
参数说明:
- format — 格式字符串。
- t1 — 可选的参数t是一个struct_time对象
- t2 — 可选的参数t是一个format time对象
>>> import time >>> time.strftime('%Y-%m-%d %X',time.localtime()) '2019-06-13 17:26:55' >>> time.strptime('2019-05-01 14:10:15','%Y-%m-%d %X') time.struct_time(tm_year=2019, tm_mon=5, tm_mday=1, tm_hour=14, tm_min=10, tm_sec=15, tm_wday=2, tm_yday=121, tm_isdst=-1) # 时间元组中属性及值 属性 值 tm_year(年) 比如2017 tm_mon(月) 1 - 12 tm_mday(日) 1 - 31 tm_hour(时) 0 - 23 tm_min(分) 0 - 59 tm_sec(秒) 0 - 61 tm_wday(weekday) 0 - 6(0表示周日) tm_yday(一年中的第几天) 1 - 366 tm_isdst(是否是夏令时) 默认为-1(1:是;0:否;-1:未知) 格式化时间中格式对应属性 %Y 年 Year with century as a decimal number. %m 月 Month as a decimal number [01,12]. %d 日 Day of the month as a decimal number [01,31]. %H 时 Hour (24-hour clock) as a decimal number [00,23]. %M 分 Minute as a decimal number [00,59]. %S 秒 Second as a decimal number [00,61]. %z Time zone offset from UTC. %a 周几简写(英文Sun) Locale's abbreviated weekday name. %A 周几全名(英文Sunday) Locale's full weekday name. %b 月份简写(英语Apr) Locale's abbreviated month name. %B 月份全名(英语April) Locale's full month name. %c Locale's appropriate date and time representation. %I 十二小时制小时数 Hour (12-hour clock) as a decimal number [01,12]. %p AM/PM Locale's equivalent of either AM or PM. %X 本地相应时间 %x 本地相应日期
1.1.3. 还有2种转换
因为格式化的时间字符串可读性很高,所以有时需要将时间戳或时间元组转换为格式化时间:
time.ctime() 函数把一个时间戳(按秒计算的浮点数)转化为格式化时间的形式。 如果参数未给或者为None的时候,将会默认time.time()为参数,
time.asctime()如果参数未给或者为None的时候,将会默认time.localtime()为参数。
>>> import time >>> time.ctime(1187640983) # 传入一个时间戳 'Tue Aug 21 04:16:23 2007' >>> time.asctime() # 默认time.localtime()为参数 'Thu Jun 13 18:05:58 2019' >>> time.asctime(time.localtime()) 'Thu Jun 13 18:06:37 2019'
另外还有time.sleep()方法推迟调用程序的运行。
1.2 datetime模块
datatime模块重新封装了time模块,提供更多接口,提供的类有:date,time,datetime,timedelta,tzinfo。
这里就只看一下datetime和timedelta类:
datetime.today():返回一个表示当前本地时间的datetime对象;
datetime.now([tz]):返回一个表示当前本地时间的datetime对象,如果提供了参数tz,则获取tz参数所指时区的本地时间;
datetime.utcnow():返回一个当前utc时间的datetime对象;格林尼治时间
datetime.fromtimestamp(timestamp[, tz]):根据时间戮创建一个datetime对象,参数tz指定时区信息;
datetime.utcfromtimestamp(timestamp):根据时间戮创建一个datetime对象;格林尼治时间
datetime.combine(date, time):参数是datetime.datetime类的对象、datetime.date对象、datetime.time对象,得到一个datetime.datetime对象;
datetime.strptime(date_string, format):将格式字符串转换为datetime对象;
方法和属性
dt=datetime.datetime.now() #datetime对象
dt.year、month、day、hour、minute、second、microsecond、tzinfo:
dt.date():获取date对象;
dt.time():获取time对象;
dt. replace ([ year[ , month[ , day[ , hour[ , minute[ , second[ , microsecond[ , tzinfo] ] ] ] ] ] ] ]):
dt. timetuple ()
dt. utctimetuple ()
dt. toordinal ()
dt. weekday ()
dt. isocalendar ()
dt. isoformat ([ sep] )
dt. ctime ():返回一个日期时间的C格式字符串,等效于time.ctime(time.mktime(dt.timetuple()));
dt. strftime (format)
datetime加减
对日期和时间进行加减实际上就是把datetime往后或往前计算,得到新的datetime。加减可以直接用+
和-
运算符,不过需要导入timedelta这个类:
>>> from datetime import datetime, timedelta >>> now = datetime.now() >>> now datetime.datetime(2015, 5, 18, 16, 57, 3, 540997) >>> now + timedelta(hours=10) datetime.datetime(2015, 5, 19, 2, 57, 3, 540997) >>> now - timedelta(days=1) datetime.datetime(2015, 5, 17, 16, 57, 3, 540997) >>> now + timedelta(days=2, hours=12) datetime.datetime(2015, 5, 21, 4, 57, 3, 540997)
时区转换
我们可以先通过utcnow()
拿到当前的UTC时间,再转换为任意时区的时间:
# 拿到UTC时间,并强制设置时区为UTC+0:00: >>> utc_dt = datetime.utcnow().replace(tzinfo=timezone.utc) >>> print(utc_dt) 2015-05-18 09:05:12.377316+00:00 # astimezone()将转换时区为北京时间: >>> bj_dt = utc_dt.astimezone(timezone(timedelta(hours=8))) >>> print(bj_dt) 2015-05-18 17:05:12.377316+08:00 # astimezone()将转换时区为东京时间: >>> tokyo_dt = utc_dt.astimezone(timezone(timedelta(hours=9))) >>> print(tokyo_dt) 2015-05-18 18:05:12.377316+09:00 # astimezone()将bj_dt转换时区为东京时间: >>> tokyo_dt2 = bj_dt.astimezone(timezone(timedelta(hours=9))) >>> print(tokyo_dt2) 2015-05-18 18:05:12.377316+09:00
时区转换的关键在于,拿到一个datetime时,要获知其正确的时区,然后强制设置时区,作为基准时间。
利用带时区的datetime通过astimezone()方法,可以转换到任意时区。
注:不是必须从UTC+0:00时区转换到其他时区,任何带时区的datetime都可以正确转换,例如上述bj_dt到tokyo_dt的转换。
2、random模块
Python中的random模块用于生成随机数。下面介绍一下random模块中最常用的几个方法:
import random 1. random.random() # 用于生成一个0到1的随机浮点数:0<= n < 1.0 >>> random.random() 0.9646844371759081 2. random.uniform(a,b) # 用于生成一个指定范围内的随机符点数n: a <= n <= b >>> random.uniform(5,10) 6.584158762448463 3. random.randint(a,b) # 用于生成一个指定范围内的随机整数n: a <= n <= b >>> random.randint(4,10) 6 4. random.randrange([start],stop,step) # 从指定范围内,按指定基数递增的集合中获取一个随机数 >>> random.randrange(10,18,3) 16 5. random.choice(sequence) # 从序列sequence中获取一个随机元素 >>> random.choice('hello world') 'r' 6. random.shuffle() # 用于将一个列表中的元素打乱,即将列表内的元素随机排列 >>> p=[1,2,3,4,5,6,7] >>> random.shuffle(p) >>> p [5, 1, 6, 7, 4, 3, 2] 7. random.sample(sequence,k) # 从指定序列sequence中随机获取指定长度k的片断并随机排列。注意:sample函数不会修改原有序列。 >>> L = ['A','B','C',1,2,3] >>> random.sample(L,3) [3, 'B', 1] >>> L ['A', 'B', 'C', 1, 2, 3]
3、OS模块
os模块提供了多数操作系统的功能接口函数。当os模块被导入后,它会自适应于不同的操作系统平台,根据不同的平台进行相应的操作,
在python编程时,经常和文件、目录打交道,所以离不了os模块。
os.getcwd() 获取当前工作的目录 os.chdir(path) 改变目录到指定path目录,注意windows标准路径分隔符为‘//’ os.makedirs('dirname1/dirname2') 可生成多层递归目录 os.removedirs('dirname1') 若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推 os.mkdir('dirname') 生成单级目录 os.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 输出用于分割文件路径的字符串 os.name 输出字符串指示当前使用平台。win->'nt'; Linux->'posix' os.environ 获取系统环境变量 os.path.abspath(path) 返回path规范化的绝对路径 os.path.join(path1[, path2[, ...]]) 将多个路径组合后返回,第一个绝对路径之前的参数将被忽略 os.path.split(path) 将path分割成目录和文件名的二元组返回 os.path.splitext(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.getatime(path) 返回path所指向的文件或者目录的最后存取时间 os.path.getmtime(path) 返回path所指向的文件或者目录的最后修改时间 os.path.getsize(filename) 获取文件大小,目录返回0
还有

os.system() 用于运行外部程序 如web浏览器,在UNIX中,可以这样(找到浏览器位置) os.system('/usr/bin/firefox') 在Windows中,可以这样(同样,找到浏览器位置) os.system(r'C:"Program Files (x86)""Mozilla Firefox"firefox.exe') 注意,这里用引号将Program Files (x86)和Mozilla Firefox括起来了。如果不这样做,底层的shell将受阻与空白处,而且这里必须用反斜杠。 os.startfile() Windows特有的函数,同system,而且略微比system好用 os.system(r'C:Program Files (x86)Mozilla Firefoxfirefox.exe') os.startfile接受一个普通路径,即便有空白也没有关系 实际操作后发现后者比前者好用(Windows),不光是空白原因。
4、sys模块
sys.argv 命令行参数,包括脚本名 sys.exit([arg]) 退出当前程序,可通过可选参数指定返回值或错误消息 sys.path 返回一个列表,包含模块的搜索路径,初始化时使用PYTHONPATH环境变量的值 sys.platform 返回操作系统平台名称 sys.version 获取Python解释程序的版本信息 sys.stdin 标准输入流 —— 一个类似于文件的对象 sys.stdout 标准输出流 —— 一个类似于文件的对象 sys.stderr 标准错误流 —— 一个类似于文件的对象
关于sys.argv

# 解释为:命令行参数,包括脚本(程序本身)名 # sys.argv[]说白了就是一个从程序外部获取参数的桥梁,这个“外部”很关键,因为我们从外部取得的参数可以是多个,所以获得的是一个列表(list), # 即sys.argv其实可以看作是一个列表,所以才能用[]提取其中的元素。其第一个元素是程序本身,随后才依次是外部给予的参数。 # 下面通过一个argv_test.py的例子看下: # argv_test.py import sys a=sys.argv[0] print(a) # 然后命令行运行:python argv_test.py 得到如下结果 argv_test.py # 这就是‘0’指程序本身 # 然后将0改成1,再运行一次,这次要加上一个参数:python argv_test.py hello 得到: hello # 那我们再把代码修改一下:a=sys.argv[2:] # 保存后,再运行程序,这次多加几个参数,以空格隔开:python argv_test.py a b c d e f 得到: ['b', 'c', 'd', 'e'] # sys.argv[ ]其实就是一个列表,里边的项为用户输入的参数,关键就是要明白这参数是从程序外部输入的, # 而非代码本身的什么地方,要想看到它的效果就应该将程序保存了,从外部来运行程序并给出参数。
5、hashlib模块
Python的hashlib提供了常见的摘要算法,如MD5,SHA1等等。
什么是摘要算法呢?摘要算法又称哈希算法、散列算法。它通过一个函数,把任意长度的数据转换为一个长度固定的数据串(通常用
16进制的字符串表示)。
我们以常见的摘要算法MD5为例,计算出一个字符串的MD5值:
import hashlib md5 = hashlib.md5() md5.update('This is hashlib'.encode('utf-8')) print(md5.hexdigest()) # 执行结果如下: '4965310fcf57676786876118fd09912e'
如果内容较多可以分多次调用update,最后得到的密文和一次性输入是一样的(注意空格)。
MD5是最常见的摘要算法,速度很快,生成结果是固定的128 bit字节,通常用一个32位的16进制字符串表示
另一种常见的摘要算法是SHA1,调用SHA1和调用MD5完全类似:
import hashlib sh = hashlib.sha1() sh.update('This is '.encode('utf-8')) sh.update('hashlib'.encode('utf-8')) sh.hexdigest() # 执行结果如下: 'cb61e3638d1cffe5c3080f358a33cb526ca7458c'
比SHA1更安全的算法是SHA256和SHA512,不过越安全的算法不仅越慢,而且摘要长度更长。
有没有可能两个不同的数据通过某个摘要算法得到了相同的摘要?完全有可能,因为任何摘要算法都是把无限多的数据集合映射到一
个有限的集合中。这种情况称为碰撞,这种情况可能出现,但是非常非常困难。
6、XML处理模块
首先关于xml不做介绍,想了解可以自行搜索或者去菜鸟驿站了解一下,而且也有该模块的教程。
常见的 XML 编程接口有 DOM 和 SAX,这两种接口处理 XML 文件的方式不同,当然使用场合也不同。
Python 有三种方法解析 XML,SAX,DOM,以及 ElementTree,简单说下:
SAX:用事件驱动模型,通过触发事件和回调函数来处理XML文件,是流式读取XML文件,比较快,占用内存少,但需要用户实现回调。
DOM:将 XML 数据在内存中解析成一个树,通过对树的操作来操作XML,DOM功能齐全,但是比较笨重,一是比较慢,二是比较耗内存。
ElementTree:就像一个轻量级的DOM,具有方便友好的API。代码可用性好,速度快,消耗内存少。
这里就只简单讨论一下ElementTree解析方式
6.1 API名称
from xml.etree import ElementTree as ET
6.2 基本概念
<country name="Liechtenstein"> <rank>1</rank> <year>2008</year> <gdppc>141100</gdppc> <neighbor name="Austria" direction="E"/> <neighbor name="Switzerland" direction="W"/> </country> 我们把<country>xxx</contry>这种结构称为一个element,country称作element的tag,<></>之间的内容称作element的text或data,<>中的name称作element的attrib,而整个XML树被称作ElementTree。 element是一个名为xml.etree.ElementTree.Element的类,其描述为: class xml.etree.ElementTree.Element(tag, attrib={}, **extra) 此类的所有属性和方法查看: https://docs.python.org/2/library/xml.etree.elementtree.html #element-objects
6.3 方法释义
读取xml数据
--读取XML文件 import xml.etree.ElementTree as ET tree = ET.parse('country_data.xml') root = tree.getroot() --读取XML字符串 root = ET.fromstring(country_data_as_string) --获取element object的四大属性tag、text、attrib以及tail root.tag #root element的tag root.text #root element的text root.attrib #root element本身的attrib,dict格式的 root.tail #root element的tag结束到下一个tag之间的text --通过DICT逻辑获取树形结构的text,表示第一个child的第二个child element的text root[0][1].text
element object的方法
Element.iter(tag) --遍历当前element树所有子节点的element(无论是子节点还是子节点的子节点),找到符合指定tag名的所有element,如果tag为空则遍历当前element树,返回所有节点element(包含当前父节点)。2.7和3.2之前的版本无此方法,可以用getiterator()代替。 Element.findall(tag) --遍历当前节点的直接子节点,找到符合指定tag名的element,返回由element组成的list Element.find(tag) --遍历当前节点的直接子节点,找到符合指定tag名的第一个element Element.get(key) --在当前element中获取符合指定attrib名的value ...其他方法参考官网
修改XML内容
ElementTree.write(file, encoding="us-ascii", xml_declaration=None, default_namespace=None, method="xml") --将之前的修改写入XML Element.set(key,value) --设置element attrib Element.append(subelement) --新增一个子element,extends(subelements)是3.2的新增用法,输入参数必须是一个element序列 Element.remove(subelement) --删除指定tag的element 示例: >>> for rank in root.iter('rank'): ... new_rank = int(rank.text) + 1 ... rank.text = str(new_rank) ... rank.set('updated', 'yes') ... >>> tree.write('output.xml')
6.4 实例
xml的格式如下,就是通过<>节点来区别数据结构的(country_data.xml)
<?xml version="1.0"?> <data> <country name="Liechtenstein"> <rank updated="yes">2</rank> <year>2008</year> <gdppc>141100</gdppc> <neighbor name="Austria" direction="E"/> <neighbor name="Switzerland" direction="W"/> </country> <country name="Singapore"> <rank updated="yes">5</rank> <year>2011</year> <gdppc>59900</gdppc> <neighbor name="Malaysia" direction="N"/> </country> <country name="Panama"> <rank updated="yes">69</rank> <year>2011</year> <gdppc>13600</gdppc> <neighbor name="Costa Rica" direction="W"/> <neighbor name="Colombia" direction="E"/> </country> </data>
操作xml
import xml.etree.ElementTree as ET tree = ET.parse("xmltest.xml") root = tree.getroot() print(root.tag) #遍历xml文档 for child in root: print(child.tag, child.attrib) for i in child: print(i.tag,i.text) #只遍历year 节点 for node in root.iter('year'): print(node.tag,node.text)
删除、修改xml内容
import xml.etree.ElementTree as ET tree = ET.parse("xmltest.xml") root = tree.getroot() #修改 for node in root.iter('year'): new_year = int(node.text) + 1 node.text = str(new_year) node.set("updated","yes") tree.write("xmltest.xml") #删除node for country in root.findall('country'): rank = int(country.find('rank').text) if rank > 50: root.remove(country) tree.write('output.xml')
自己创建xml文档
import xml.etree.ElementTree as ET new_xml = ET.Element("namelist") name = ET.SubElement(new_xml,"name",attrib={"enrolled":"yes"}) age = ET.SubElement(name,"age",attrib={"checked":"no"}) sex = ET.SubElement(name,"sex") sex.text = '33' name2 = ET.SubElement(new_xml,"name",attrib={"enrolled":"no"}) age = ET.SubElement(name2,"age") age.text = '19' et = ET.ElementTree(new_xml) #生成文档对象 et.write("test.xml", encoding="utf-8",xml_declaration=True) ET.dump(new_xml) #打印生成的格式
7、json&pickle模块
通过将对象序列化可以将其存储在变量或者文件中,可以保存当时对象的状态,并且需要时可以通过反序列化再次将这个对象读取出来。
python中用于序列化的主要有两个模块
- json,如果我们要在不同的编程语言之间传递对象,就必须把对象序列化为标准格式,比如XML,但更好的方法是序列化为JSON,因为JSON表示出来就是一个字符串,可以被所有语言读取,也可以方便地存储到磁盘或者通过网络传输。JSON不仅是标准格式,并且比XML更快,而且可以直接在Web页面中读取,非常方便。
- pickle,用于python特有的类型和python的数据类型间进行转换,并且可能不同版本的Python彼此都不兼容,因此,只能用Pickle保存那些不重要的数据。
Json模块提供了四个功能:dumps和dump(序列化)、loads和load(反序列化)
pickle模块提供了四个功能:dumps、dump、loads、load
>>> import pickle # pickle.dumps()方法把任意对象序列化成一个bytes >>> data = dict(name='Eric',age=23,score=59) >>> d = pickle.dumps(data) >>> d b'x80x03}qx00(Xx04x00x00x00nameqx01Xx04x00x00x00Ericqx02Xx03x00x00x00ageqx03Kx17Xx05x00x00x00scoreqx04K;u.' # pickle.dump()直接把对象序列化后写入一个文件 >>> f = open('info.txt','wb') >>> pickle.dump(data,f) >>> f.close() # pickle.loads()方法可以把bytes反序列化 >>> pickle.loads(d) {'name': 'Eric', 'age': 23, 'score': 59} # pickle.load()方法从一个文件中直接反序列化出对象 >>> f = open('info.txt','rb') >>> data_1=pickle.load(f) >>> data_1 {'name': 'Eric', 'age': 23, 'score': 59}
json进阶
JSON表示的对象就是标准的JavaScript语言的对象,JSON和Python内置的数据类型对应如下:
JSON类型 | Python类型 |
---|---|
{} | dict |
[] | list |
"string" | str |
1234.56 | int或float |
true/false | True/False |
null | None |
Python的dict对象可以直接序列化为JSON的{},不过,很多时候,大家更喜欢用class表示对象,比如定义Students类,然后序列化:
import json class Student(object): def __init__(self, name, age, score): self.name = name self.age = age self.score = score s = Student('Eric', 20, 59) print(json.dumps(s)) # 执行结果如下: Traceback (most recent call last): ... TypeError:Object of type Student is not JSON serializable
错误的原因是Student对象不是一个可序列化为JSON的对象
仔细看看dump()方法的参数列表,可以发现,除了第一个必须的obj参数外,dump()方法还提供了一大堆的可选参数:
https://docs.python.org/3/library/json.html#json.dumps
可选参数default就是把任意一个对象变成一个可序列为JSON的对象,这里需要把class转换成dict:
print(json.dumps(s, default=lambda obj: obj.__dict__))
因为通常class的实例都有一个__dict__属性,它就是一个dict,用来存储实例变量。
同样的道理,如果我们要把JSON反序列化为一个Student对象实例,load()方法首先转换出一个dict对象,然后,我们传入的object_hook函数把dict实例Student实例:
def dict2student(d): return Student(d['name'], d['age'], d['score'])
即有:
s = Student('Eric', 20, 59) #序列化 f = open('class_pickle.txt', 'w') json.dump(s, f, default=lambda obj: obj.__dict__) f.close() # 反序列化 def dict2studend(d): return Student(d['name'], d['age'], d['score']) f = open('class_pickle.txt', 'r') d = json.load(f, object_hook=dict2studend) f.close() print(d)