常见内置模块

datetime是Python处理日期和时间的标准库。

datetime是模块,datetime模块还包含一个datetime类,通过from datetime import datetime导入的才是datetime这个类

datetime

from datetime import datetime 

now=datetime.now() # 获取当前时间
print(now)  # 2018-08-03 15:06:09.944095
print(type(now)) # <class 'datetime.datetime'>

date1=datetime(2015, 10, 8, 1, 11)  # 创建指定日期时间
print(date1)  # 2015-10-08 01:11:00

# 在计算机中 时间使用数字(时间戳)表示的

timestamp=date1.timestamp() #将datetime转为时间戳
print(timestamp) # 1444237860.0

date2=datetime.fromtimestamp(timestamp) # 将时间戳转为本地时间
date3=datetime.utcfromtimestamp(timestamp) #将时间转为UTC时间
print(date2)  # 2015-10-08 01:11:00
print(date3) # 2015-10-07 17:11:00

# str转date
date4=datetime.strptime("2015-6-1 18:19:59", "%Y-%m-%d %H:%M:%S") 
print(date4) # 2015-06-01 18:19:59

# date转str
str1=date4.strftime("%a, %b %d %H:%M")
print(str1)  # Mon, Jun 01 18:19


# 时间增减
from datetime import datetime, timedelta

now1=datetime.now()
newdate1=now1+timedelta(hours=12)  # 增加12小时的时间
newdate2=now1-timedelta(days=2, minutes=50)
print(newdate1) # 2018-08-04 04:09:26.450345
print(newdate2) # 2018-08-01 16:25:14.299462



# datetime 有一个时区属性tzinfo 但是默认为 None 因此无法区分时间的时区 我们可以给其设置一个时区,帮助区分是哪个时区的时间

from datetime import datetime, timedelta, timezone

tz_utc_8=timezone(timedelta(hours=8))
print(tz_utc_8)  # UTC+08:00

print(now) # 2018-08-03 17:26:29.846861
date_utc_8=now.replace(tzinfo=tz_utc_8)

print(date_utc_8)  # 2018-08-03 17:26:29.846861+08:00

# 获取当前的utc时间 并且加上utc时区信息
utc_dt=datetime.utcnow().replace(tzinfo=timezone.utc)
print(utc_dt) # 2018-08-03 09:30:57.959514+00:00
print(datetime.utcnow()) # 2018-08-03 09:30:57.959525
print(timezone.utc) # UTC

# 将utc时间转为北京时区时间
bj_dt=utc_dt.astimezone(timezone(timedelta(hours=8)))
print(bj_dt) # 2018-08-03 17:39:22.703278+08:00

datetime有一个时区属性tzinfo 但是默认为 None 因此无法区分时间的时区 我们可以给其设置一个时区,帮助区分是哪个时区的时间

任何带时区新的date 都可以转换时间

要存储datetime,最佳方法是将其转换为timestamp再存储,因为timestamp的值与时区完全无关

collections

内置的一个集合模块 提供了许多有用的集合类

namedtuple

是一个用来创建自定义的tuple对象,规定了元素个数,可以用属性而不是索引来引用tuple中的元素


from collections import namedtuple
Point=namedtuple("point", ["x", "y"])
p1=Point(2, 3)

print("坐标为 %s %s" % (p1.x, p1.y)) # 坐标为 2 3

isinstance(p1, Point) #True

deque

为了弥补list线性存储插入和删除元素慢,deque是双向列表,适合于队列和栈,除了实现了list的append()pop()外,还支持appendleft()popleft(),可以方便的向头部添加或删除数据

from collections import deque
q1=deque(["1", "2", "3"])
q1.append("x")
q1.appendleft("y")
print(q1)  # deque(['y', '1', '2', '3', 'x'])

defaultdict

dict中引用的key不存在时,返回默认值
默认值是调用函数返回的,而函数在创建defaultdict对象时传入。

from collections import defaultdict
dd1=defaultdict(lambda:"defaultValue")
dd1["key1"]="abc"
print(dd1["key1"]) # abc
print(dd1["key2"]) # defaultValue

OrderedDict

dict是无序的 如果要保持key顺序 可以使用OrderedDict,OrderedDict会按照插入的顺序排除

Counter

简单的计数器,也是dict的一个子类

from collections import Counter
c1=OrderedDict()
for char in "programming":
    c1[char]=c1[char]+1
print(c1)
# Counter({'r': 2, 'g': 2, 'm': 2, 'p': 1, 'o': 1, 'a': 1, 'i': 1, 'n': 1})

base64

base64将3字节的数据编码为4字节,长度增加了33%,如果不足的话会用0x00在末尾补全,然后在末尾加同样数量的=标识,这样解码的时候会自动去掉

Python内置的有base64编码方法
由于标准的base64编码后可能出现字符+和/ 不能在url中作为参数,因此可以受用url safe的base64,将+和/换位-和_

import base64
b64encodestr1=base64.b64encode(b"binary\x00string")
print(b64encodestr1) # b'YmluYXJ5AHN0cmluZw=='
b64decodestr2=base64.b64decode(b64encodestr1)
print(b64decodestr2) # b'binary\x00string'

#urlsafe_b64encode
base64encodestr2=base64.b64encode(b"i\xb7\x1d\xfb\xef\xff")
print(base64encodestr2) # b'abcd++//'
base64urlsafeencode=base64.urlsafe_b64encode(b"i\xb7\x1d\xfb\xef\xff")
print(base64urlsafeencode) # b'abcd--__'

struct

python内置了struct模块来解决bytes和其它二进制数据类型的转换

import struct
struct1=struct.pack(">I", 10240099)
print(struct1) # b'\x00\x9c@c'

struct2=struct.unpack(">IH", b"\xf0\xf0\xf0\xf0\x80\x80")
print(struct2) # (4042322160, 32896)

参数中>表示网络序的大端, I:4字节无符号整数 H:2字节无符号整数

hashlib

python提供摘要算法,包括MD5 SHA1等

MD5摘要

import hashlib
#md5()可以不加参数 然后update()内容 如果内容过多也可以多次 update
md5=hashlib.md5("到付奥佛八奥保护管安排表佛八".encode("utf-8"))
md5.update("dddd".encode("utf-8"))
print(md5.hexdigest()) # a459918710ca186970b2ed69cedee466

SHA1摘要

import hashlib

sha1 = hashlib.sha1()
sha1.update('how to use sha1 in '.encode('utf-8'))
sha1.update('python hashlib?'.encode('utf-8'))
print(sha1.hexdigest())

hmac

只是简单的摘要哈希的话,有被黑客破译的风险,这时候我们经常需要做加盐处理

import hmac
message=b"Hello, world"
key=b"secert"
h=hmac.new(key, message, digestmod="MD5")
print(h.hexdigest())  # 4f05d03996e3c5c96ccde51100246253

itertools

itertools提供了有用于操作迭代对象的函数

import itertools
# 创建几个 无限重复序列


natuals=itertools.count(1) # 1 2 3 4 ....
cs=itertools.cycle("ABc") # A B C A B C ...
ns=itertools.repeat("A") # A A A A A A ...
# 可以加第二个参数 指定重复次数
ns=itertools.repeat("A", 3) # A A A

takewhile()

对于itertools无限序列,通常用takewhile()截取有用序列

natuals1=itertools.count(1)
result1=itertools.takewhile(lambda x : x<4, natuals1)
print(list(result1)) # [1, 2, 3]

chain()

chain()可以把一组迭代对象串联起来,形成一个更大的迭代器

for c in itertools.chain('ABC', 'XYZ'):
     print(c)
# 迭代效果:'A' 'B' 'C' 'X' 'Y' 'Z'

groupby()

groupby()把迭代器中相邻的重复元素挑出来放在一起:

for key, group in itertools.groupby('AAABBBCCAAA'):
     print(key, list(group))

A ['A', 'A', 'A']
B ['B', 'B', 'B']
C ['C', 'C']
A ['A', 'A', 'A']

# 挑选规则实际上是通过函数完成的
for key, group in itertools.groupby('AaaBBbcCAAa', lambda c: c.upper()):
     print(key, list(group))

A ['A', 'a', 'a']
B ['B', 'B', 'b']
C ['c', 'C']
A ['A', 'A', 'a']

contextlib

对于读写文件我们已经使用过with()语句 其实只要实现了上下文管理都可以使用with语句

urllib

urllib内建模块提供了操作url功能

get

POST

XML

操作XML通常有两种方法:DOM和SAX

DOM会把整个XML读入内存,可以解析遍历树的任何节点,缺点是占用内存大,解析慢
SAX是流模式,边读边解析,占用内存小,解析快,缺点是需要自己处理事件
通常选择SAX 因为DOM太耗内存

from xml.parsers.expat import ParserCreate

class DefaultSaxHandler(object):
    def start_element(self, name, attrs):
        print('sax:start_element: %s, attrs: %s' % (name, str(attrs)))

    def end_element(self, name):
        print('sax:end_element: %s' % name)

    def char_data(self, text):
        print('sax:char_data: %s' % text)

xml = r'''<?xml version="1.0"?>
<ol>
    <li><a href="/python">Python</a></li>
    <li><a href="/ruby">Ruby</a></li>
</ol>
'''

handler = DefaultSaxHandler()
parser = ParserCreate()
parser.StartElementHandler = handler.start_element
parser.EndElementHandler = handler.end_element
parser.CharacterDataHandler = handler.char_data
parser.Parse(xml)

需要注意的是读取一大段字符串时,CharacterDataHandler可能被多次调用,所以需要自己保存起来,在EndElementHandler里面再合并。

因为XML解析太复杂 建议你改用JSON

HTMLParser

当需要解析HTML内容时,因为HTML的语法没有XML那么严格,所以不能用标准的DOMSAX解析,python提供了HTMLParser来解析HTML

from html.parser import HTMLParser
from html.entities import name2codepoint

class MyHTMLParser(HTMLParser):

    def handle_starttag(self, tag, attrs):
        print('<%s>' % tag)

    def handle_endtag(self, tag):
        print('</%s>' % tag)

    def handle_startendtag(self, tag, attrs):
        print('<%s/>' % tag)

    def handle_data(self, data):
        print(data)

    def handle_comment(self, data):
        print('<!--', data, '-->')

    def handle_entityref(self, name):
        print('&%s;' % name)

    def handle_charref(self, name):
        print('&#%s;' % name)

parser = MyHTMLParser()
parser.feed('''<html>
<head></head>
<body>
<!-- test html parser -->
    <p>Some <a href=\"#\">html</a> HTML&nbsp;tutorial...<br>END</p>
</body></html>''')

feed()方法可以多次调用,也就是不一定一次把整个HTML字符串都塞进去,可以一部分一部分塞进去。

特殊字符有两种,一种是英文表示的&nbsp;,一种是数字表示的&#1234;,这两种字符都可以通过Parser解析出来。