2.7. 常见模块

2.7.1. datetime

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

datetime表示的时间需要时区信息才能确定一个特定的时间,否则只能视为本地时间。

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

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# 获取当前日期
import datetime 
now = datetime.datetime.now()
print(now)
print(type(now))

# 获取指定日期和时间
dt = datetime.datetime(2024, 1, 2, 12, 20)
print(dt)


# datetime转换为timestamp
# timestamp = 0 = 1970-1-1 00:00:00 UTC+0:00

dt = datetime.datetime(2024, 1, 2, 12, 20)
print(dt.timestamp())

# timestamp转换为datetime
dt = datetime.datetime.fromtimestamp(dt.timestamp())
print(dt)
print(datetime.utcfromtimestamp(dt)) # UTC时间

# str 2 datetime 

import datetime 
now =datetime.datetime.strptime("2024-01-01 18:00:00",'%Y-%m-%d %H:%M:%S')
print(now)

# datetime 2 str 

now_str =datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
print(now_str)

# 日期加减

now = datetime.datetime.now()
now + datetime.timedelta(hours=10,days=-1)

# 本地时间转化为utc时间

tz_utc_8 = datetime.timezone(datetime.timedelta(hours=8))
now = datetime.datetime.now()
print(now)
dt = now.replace(tzinfo=tz_utc_8)
print(dt)

# 时区转化

utc_now = datetime.datetime.utcnow().replace(tzinfo=datetime.timezone.utc)
bj_dt = utc_now.astimezone(datetime.timezone(datetime.timedelta(hours=8)))
print(utc_now)
print(bj_dt)





2.7.2. collections

collection是python内建的一个集合模块,提供了许多有用的集合类。

namedtuple

namedtuple是一个函数,它用来创建一个自定义的tuple对象。

from collections import namedtuple

Point  = namedtuple('Point',['x','y'])
p  = Point(1,2)
print(p.x)
print(p.y)

deque

deque是为了高效实现插入和删除操作的双向列表,适合用于队列和栈。 list不适合频繁插入删除。

from collections import deque

q = deque(['a','b','c'])
q.append('d')
q.appendleft('y')
print(q)

defaultdict

如果希望key不存在时,返回一个默认值,就可以用defaultdict。

from collections import defaultdict 

dd = defaultdict(lambda: 'N/A')
print(dd["k1"])

OrderedDict

如果要保持Key的顺序,可以用OrderedDict。

from collections import OrderedDict
d = OrderedDict([('a', 1), ('b', 2), ('c', 3)])
print(d)

ChainMap

ChainMap是可以把一组dict串起来组成的逻辑dict,会优先查找内部的dict,依次查找外部。


from collections import ChainMap 
import os 

d1 = { 
    'color': 'red',
    'user': 'zhaojiedi'
}
d2 = {
      'color': 'blue'
}
d3 = {
      'age': 1,
}

combined = ChainMap(d1,d2,d3)
print(combined['color'])
print(combined['age'])

Counter

counter是一个简单的计数器。


from collections import Counter 
c =Counter() 
c.update('hello')
print(c)

2.7.3. argparser

argparse是用于解析命令行参数的。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import argparse 

def main(): 
    
    p = argparse.ArgumentParser(
        prog='backup',
        description='backup db',
        epilog='copyright ,2023'
    )
    p.add_argument('outfile')
    p.add_argument('--host',default='localhost')
    p.add_argument('--port',default=3306,type=int)
    p.add_argument('-u', '--user', required=True)
    p.add_argument('-p', '--password', required=True)
    p.add_argument('--database', required=True)
    p.add_argument('-gz', '--gzcompress', action='store_true', required=False, help='Compress backup files by gz.')

    args = p.parse_args()
    print(args)


if __name__ == '__main__':
    # (venv) ➜  My_Study_Python git:(master) ✗ python3 ./source/code/14.03.argparse.py  -uroot -poracle --database d1 -gz a.txt
    # Namespace(outfile='a.txt', host='localhost', port=3306, user='root', password='oracle', database='d1', gzcompress=True)
    main()

2.7.4. base64

base64是一种64个字符来表示任意二进制数据的方法。

base64是64个字符,包含26个字母的大写和小写,数字10个,另外包含’+’ 和 ‘/’ 。

在urlsafe中,将’+’变成’-’,将’/’变成’_’。

In [5]: base64.b64encode(b'i\xb7\x1d\xfb\xef\xff')
Out[5]: b'abcd++//'

In [6]: base64.urlsafe_b64encode(b'i\xb7\x1d\xfb\xef\xff')
Out[6]: b'abcd--__'

2.7.5. struct

todo

2.7.6. hashlib

可以通过hashlib计算摘要信息。

In [7]: import hashlib

In [8]: md5 = hashlib.md5()

In [9]: md5.update('zhaojiedi'.encode('utf-8'))

In [10]: md5.hexdigest()
Out[10]: 'efb605a4a365423301d33afec4138813'

2.7.7. hmac

In [1]: import hmac

In [2]: message=b'abc'

In [3]: key=b'secret'

In [4]: h = hmac.new(key,message,digestmod='md5')

In [5]: h.hexdigest()
Out[5]: 'd9bf7c3a63eae7031c4e6d7c9b78ba93'

2.7.8. itertools

# 三个字母循环的。
cs = itertools.cycle('ABC')

# 重复一个元素多次
ns = itertools.repeat('A', 3)

# 提前特定个数
itertools.takewhile(lambda x: x <= 10, natuals)

# 整合一个大的
for c in itertools.chain('ABC', 'XYZ'):

# groupby()把迭代器中相邻的重复元素挑出来放在一起:
for key, group in itertools.groupby('AAABBBCCAAA'):
    print(key, list(group))

2.7.9. contextlib

实现上下文管理是通过__enter__和__exit__这两个方法实现的。

编写__enter__和__exit__仍然很繁琐,因此Python的标准库contextlib提供了更简单的写法

如果一个对象没有实现上下文,我们就不能把它用于with语句。这个时候,可以用closing()来把该对象变为上下文对象

#!/usr/bin/env python3
# -*- coding: utf-8 -*-


class Query(object):

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

    def __enter__(self):
        print('start')
        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)


with Query("abc") as f:
    f.query()



from contextlib import contextmanager

class QueryV2(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 = QueryV2(name)
    yield q
    print('End')


with create_query("abc") as q: 
    q.query()



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

with tag("h1"):
    print("hello")
    print("world")

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
def closing(thing):
    try:
        yield thing
    finally:
        thing.close()

2.7.10. request

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from urllib import request
with request.urlopen('https://api.douban.com/v2/book/2129650') as f:
    data = f.read()
    print(f.status)
    print(data)

# todo post