【Python】【整理】廖雪峯Python教程代碼整理—— 13、常用內建模塊

常用內建模塊

13.1 datetime

獲取當前日期和時間

>>> from datetime import datetime
>>> now = datetime.now() # 獲取當前datetime
>>> print(now)
2015-05-18 16:28:07.198690
>>> print(type(now))
<class 'datetime.datetime'>

獲取指定日期和時間

>>> from datetime import datetime
>>> dt = datetime(2015, 4, 19, 12, 20) # 用指定日期時間創建datetime
>>> print(dt)
2015-04-19 12:20:00

datetime轉換爲timestamp

>>> from datetime import datetime
>>> dt = datetime(2015, 4, 19, 12, 20) # 用指定日期時間創建datetime
>>> dt.timestamp() # 把datetime轉換爲timestamp
1429417200.0

timestamp轉換爲datetime

>>> from datetime import datetime
>>> t = 1429417200.0
>>> print(datetime.fromtimestamp(t))
2015-04-19 12:20:00

timestamp直接轉換到UTC標準時區的時間:

>>> from datetime import datetime
>>> t = 1429417200.0
>>> print(datetime.fromtimestamp(t)) # 本地時間
2015-04-19 12:20:00
>>> print(datetime.utcfromtimestamp(t)) # UTC時間
2015-04-19 04:20:00

str轉換爲datetime.

>>> from datetime import datetime
>>> cday = datetime.strptime('2015-6-1 18:19:59', '%Y-%m-%d %H:%M:%S')
>>> print(cday)
2015-06-01 18:19:59

datetime轉換爲str

>>> from datetime import datetime
>>> now = datetime.now()
>>> print(now.strftime('%a, %b %d %H:%M'))
Mon, May 05 16:28

datetime加減

>>> 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)

本地時間轉換爲UTC時間

>>> from datetime import datetime, timedelta, timezone
>>> tz_utc_8 = timezone(timedelta(hours=8)) # 創建時區UTC+8:00
>>> now = datetime.now()
>>> now
datetime.datetime(2015, 5, 18, 17, 2, 10, 871012)
>>> dt = now.replace(tzinfo=tz_utc_8) # 強制設置爲UTC+8:00
>>> dt
datetime.datetime(2015, 5, 18, 17, 2, 10, 871012, tzinfo=datetime.timezone(datetime.timedelta(0, 28800)))

時區轉換

# 拿到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

13.2 collections

namedtuple

定義一個二維座標:

>>> from collections import namedtuple
>>> Point = namedtuple('Point', ['x', 'y'])
>>> p = Point(1, 2)
>>> p.x
1
>>> p.y
2

用座標和半徑表示一個圓:

# namedtuple('名稱', [屬性list]):
Circle = namedtuple('Circle', ['x', 'y', 'r'])

deque

>>> from collections import deque
>>> q = deque(['a', 'b', 'c'])
>>> q.append('x')
>>> q.appendleft('y')
>>> q
deque(['y', 'a', 'b', 'c', 'x'])

defaultdict

>>> from collections import defaultdict
>>> dd = defaultdict(lambda: 'N/A')
>>> dd['key1'] = 'abc'
>>> dd['key1'] # key1存在
'abc'
>>> dd['key2'] # key2不存在,返回默認值
'N/A'

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)])

FIFO:

from collections import OrderedDict

class LastUpdatedOrderedDict(OrderedDict):

    def __init__(self, capacity):
        super(LastUpdatedOrderedDict, self).__init__()
        self._capacity = capacity

    def __setitem__(self, key, value):
        containsKey = 1 if key in self else 0
        if len(self) - containsKey >= self._capacity:
            last = self.popitem(last=False)
            print('remove:', last)
        if containsKey:
            del self[key]
            print('set:', (key, value))
        else:
            print('add:', (key, value))
        OrderedDict.__setitem__(self, key, value)

ChainMap

from collections import ChainMap
import os, argparse

# 構造缺省參數:
defaults = {
    'color': 'red',
    'user': 'guest'
}

# 構造命令行參數:
parser = argparse.ArgumentParser()
parser.add_argument('-u', '--user')
parser.add_argument('-c', '--color')
namespace = parser.parse_args()
command_line_args = { k: v for k, v in vars(namespace).items() if v }

# 組合成ChainMap:
combined = ChainMap(command_line_args, os.environ, defaults)

# 打印參數:
print('color=%s' % combined['color'])
print('user=%s' % combined['user'])

$ python3 use_chainmap.py
color=red
user=guest

$ python3 use_chainmap.py -u bob
color=red
user=bob

$ user=admin color=green python3 use_chainmap.py -u bob
color=green
user=bob

Counter

統計字符出現的個數:

>>> from collections import Counter
>>> c = Counter()
>>> for ch in 'programming':
...     c[ch] = c[ch] + 1
...
>>> c
Counter({'g': 2, 'm': 2, 'r': 2, 'a': 1, 'i': 1, 'o': 1, 'n': 1, 'p': 1})

13.3 base64

base64的編解碼:

>>> import base64
>>> base64.b64encode(b'binary\x00string')
b'YmluYXJ5AHN0cmluZw=='
>>> base64.b64decode(b'YmluYXJ5AHN0cmluZw==')
b'binary\x00string'

"url safe"的base64編碼:

>>> base64.b64encode(b'i\xb7\x1d\xfb\xef\xff')
b'abcd++//'
>>> base64.urlsafe_b64encode(b'i\xb7\x1d\xfb\xef\xff')
b'abcd--__'
>>> base64.urlsafe_b64decode('abcd--__')
b'i\xb7\x1d\xfb\xef\xff'

13.4 struct

把一個32位無符號整數變成字節,也就是4個長度的bytes:

>>> n = 10240099
>>> b1 = (n & 0xff000000) >> 24
>>> b2 = (n & 0xff0000) >> 16
>>> b3 = (n & 0xff00) >> 8
>>> b4 = n & 0xff
>>> bs = bytes([b1, b2, b3, b4])
>>> bs
b'\x00\x9c@c'

pack函數把任意數據類型變成bytes:

>>> import struct
>>> struct.pack('>I', 10240099)
b'\x00\x9c@c'

unpack把bytes變成相應的數據類型:

>>> struct.unpack('>IH', b'\xf0\xf0\xf0\xf0\x80\x80')
(4042322160, 32896)

13.5 hashlib

計算出一個字符串的MD5值:

import hashlib

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

大數據量分開調用:

import hashlib

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

調用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())

加鹽:

def calc_md5(password):
    return get_md5(password + 'the-Salt')

13.6 hmac

>>> import hmac
>>> message = b'Hello, world!'
>>> key = b'secret'
>>> h = hmac.new(key, message, digestmod='MD5')
>>> # 如果消息很長,可以多次調用h.update(msg)
>>> h.hexdigest()
'fa4ee7d173f2d97ee79022d1a7355bcf'

13.7 itertools

“無限”迭代器:

>>> import itertools
>>> natuals = itertools.count(1)
>>> for n in natuals:
...     print(n)
...
1
2
3
...
>>> import itertools
>>> cs = itertools.cycle('ABC') # 注意字符串也是序列的一種
>>> for c in cs:
...     print(c)
...
'A'
'B'
'C'
'A'
'B'
'C'
...
>>> ns = itertools.repeat('A', 3)
>>> for n in ns:
...     print(n)
...
A
A
A

根據條件判斷來截取出一個有限的序列:

>>> natuals = itertools.count(1)
>>> ns = itertools.takewhile(lambda x: x <= 10, natuals)
>>> list(ns)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

chain()

把一組迭代對象串聯起來:

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

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']

13.8 contextlib

正確關閉文件資源:

try:
    f = open('/path/to/file', 'r')
    f.read()
finally:
    if f:
        f.close()

可以簡化爲:

with open('/path/to/file', 'r') as f:
    f.read()

__enter__和__exit__這兩個方法實現:

class Query(object):

    def __init__(self, name):
        self.name = name

    def __enter__(self):
        print('Begin')
        return self
    
    def __exit__(self, exc_type, exc_value, traceback):
        if exc_type:
            print('Error')
        else:
            print('End')
    
    def query(self):
        print('Query info about %s...' % self.name)

@contextmanager

from contextlib import contextmanager

class Query(object):

    def __init__(self, name):
        self.name = name

    def query(self):
        print('Query info about %s...' % self.name)

@contextmanager
def create_query(name):
    print('Begin')
    q = Query(name)
    yield q
    print('End')


with create_query('Bob') as q:
    q.query()

在某段代碼執行前後自動執行特定代碼:

@contextmanager
def tag(name):
    print("<%s>" % name)
    yield
    print("</%s>" % name)

with tag("h1"):
    print("hello")
    print("world")
 <h1> 
hello
 world 
</h1>

@closing

closing()來把該對象變爲上下文對象:

from contextlib import closing
from urllib.request import urlopen

with closing(urlopen('https://www.python.org')) as page:
    for line in page:
        print(line)

編寫經過@contextmanager裝飾的generator:

@contextmanager
def closing(thing):
    try:
        yield thing
    finally:
        thing.close()

13.9 urllib

Get

from urllib import request

with request.urlopen('http://news-at.zhihu.com/api/4/news/latest') as f:
    data = f.read()
    print('Status:', f.status, f.reason)
    for k, v in f.getheaders():
        print('%s: %s' % (k, v))
    print('Data:', data.decode('utf-8'))
在這裏插入代碼片

Status: 200 OK
Date: Wed, 28 Aug 2019 14:40:13 GMT
Content-Type: application/json; charset=UTF-8
Content-Length: 1886
Connection: close
Set-Cookie: tgw_l7_route=060f637cd101836814f6c53316f73463; Expires=Wed, 28-Aug-2019 14:55:13 GMT; Path=/
Vary: Accept-Encoding
Etag: “89b922d6b5a834afed1c8a268c502560f5a8fab7”
X-Backend: zhihu-daily-web–28-b991030d-1538061071-80q05
X-Backend-Response: 0.003
Server: ZWS
Set-Cookie: _xsrf=FIIuaqUshsQI7zQW26VQvFcVWZSYmXFc; path=/; domain=zhihu.com; expires=Sun, 13-Feb-22 14:40:13 GMT
Data: {“date”:“20190828”,“stories”:[{“images”:[“https://pic2.zhimg.com/v2-9e100685bccb7003c2bcb47e867bb701.jpg”],“type”:0,“id”:9714698,“ga_prefix”:“082820”,“title”:“如果中國人登月把美國人插的國旗拔掉了,美國會怎麼做?”},{“images”:[“https://pic3.zhimg.com/v2-e43801aeff53dca7d6757b56eaafde32.jpg”],“type”:0,“id”:9714693,“ga_prefix”:“082816”,“title”:“隻身一貓摧毀 220 個鳥巢,這就是你家樓下流浪貓的威力”},{“images”:[“https://pic2.zhimg.com/v2-b7f0ec9c089d9912f18a1d72ba2bc1c9.jpg”],“type”:0,“id”:9714643,“ga_prefix”:“082809”,“title”:“爲什麼很多綜藝總逃不過越做越爛?”},{“images”:[“https://pic2.zhimg.com/v2-603ab71e4f2cc84d6e21493245913029.jpg”],“type”:0,“id”:9714675,“ga_prefix”:“082807”,“title”:“魚的記憶只有 7 秒?假的”},{“images”:[“https://pic2.zhimg.com/v2-1dbacbcf143a7af56387f61d649952c1.jpg”],“type”:0,“id”:9714613,“ga_prefix”:“082806”,“title”:“瞎扯 · 如何正確地吐槽”}],“top_stories”:[{“image”:“https://pic4.zhimg.com/v2-9326d71b99346b8d1936b7b0e2923e63.jpg”,“type”:0,“id”:9714689,“ga_prefix”:“082620”,“title”:“如何用一天,看盡新中國的 70 年?”},{“image”:“https://pic3.zhimg.com/v2-2898291c30691b4cfcd124cb1c89e652.jpg”,“type”:0,“id”:9714532,“ga_prefix”:“082207”,“title”:“A battle of Title: 「稱呼」是一種「信仰」”},{“image”:“https://pic3.zhimg.com/v2-524f820a813aa01296f448da039523ce.jpg”,“type”:0,“id”:9714537,“ga_prefix”:“082422”,“title”:“小事 · 一通操作猛如虎”},{“image”:“https://pic4.zhimg.com/v2-addc8595bf741cf5d6b338daf37fddbf.jpg”,“type”:0,“id”:9714217,“ga_prefix”:“080907”,“title”:“是什麼,讓人們開始質疑登月的真實性?”},{“image”:“https://pic4.zhimg.com/v2-5dcae1b99de59420bce76f543dc7977b.jpg”,“type”:0,“id”:9714198,“ga_prefix”:“080916”,“title”:“氧氣到底是生命的救濟,還是慢性的毒藥?”}]}
Process finished with exit code 0

模擬瀏覽器發送GET請求:

from urllib import request

req = request.Request('http://www.douban.com/')
req.add_header('User-Agent', 'Mozilla/6.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/8.0 Mobile/10A5376e Safari/8536.25')
with request.urlopen(req) as f:
    print('Status:', f.status, f.reason)
    for k, v in f.getheaders():
        print('%s: %s' % (k, v))
    print('Data:', f.read().decode('utf-8'))

Post

模擬一個微博登錄,先讀取登錄的郵箱和口令,然後按照weibo.cn的登錄頁的格式以username=xxx&password=xxx的編碼傳入:

from urllib import request, parse

print('Login to weibo.cn...')
email = input('Email: ')
passwd = input('Password: ')
login_data = parse.urlencode([
    ('username', email),
    ('password', passwd),
    ('entry', 'mweibo'),
    ('client_id', ''),
    ('savestate', '1'),
    ('ec', ''),
    ('pagerefer', 'https://passport.weibo.cn/signin/welcome?entry=mweibo&r=http%3A%2F%2Fm.weibo.cn%2F')
])

req = request.Request('https://passport.weibo.cn/sso/login')
req.add_header('Origin', 'https://passport.weibo.cn')
req.add_header('User-Agent', 'Mozilla/6.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/8.0 Mobile/10A5376e Safari/8536.25')
req.add_header('Referer', 'https://passport.weibo.cn/signin/login?entry=mweibo&res=wel&wm=3349&r=http%3A%2F%2Fm.weibo.cn%2F')

with request.urlopen(req, data=login_data.encode('utf-8')) as f:
    print('Status:', f.status, f.reason)
    for k, v in f.getheaders():
        print('%s: %s' % (k, v))
    print('Data:', f.read().decode('utf-8'))

Handler

proxy_handler = urllib.request.ProxyHandler({'http': 'http://www.example.com:3128/'})
proxy_auth_handler = urllib.request.ProxyBasicAuthHandler()
proxy_auth_handler.add_password('realm', 'host', 'username', 'password')
opener = urllib.request.build_opener(proxy_handler, proxy_auth_handler)
with opener.open('http://www.example.com/login.html') as f:
    pass

13.10 XML

DOM vs SAX

SAX解析器讀節點:

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)

生成XML:

L = []
L.append(r'<?xml version="1.0"?>')
L.append(r'<root>')
L.append(encode('some & data'))
L.append(r'</root>')
return ''.join(L)

13.11 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>''')
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章