美文网首页
常用内建模块2

常用内建模块2

作者: 渔家傲_俞 | 来源:发表于2018-11-29 10:51 被阅读0次

    struct

    Python提供了一个struct模块来解决bytes和其他二进制数据类型的转换。
    structpack函数把任意数据类型变成bytes

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

    pack的第一个参数是处理指令,'>I'的意思是:
    >表示字节顺序是big-endian,也就是网络序,I表示4字节无符号整数。
    后面的参数个数要和处理指令一致。
    unpackbytes变成相应的数据类型:

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

    hashlib

    Python的hashlib提供了常见的摘要算法,如MD5,SHA1等等。
    什么是摘要算法呢?摘要算法又称哈希算法、散列算法。它通过一个函数,把任意长度的数据转换为一个长度固定的数据串(通常用16进制的字符串表示)。
    举个例子,你写了一篇文章,内容是一个字符串'how to use python hashlib - by Michael',并附上这篇文章的摘要是'2d73d4f15c0db7f5ecb321b6a65e5d6d'。如果有人篡改了你的文章,并发表为'how to use python hashlib - by Bob',你可以一下子指出Bob篡改了你的文章,因为根据'how to use python hashlib - by Bob'计算出的摘要不同于原始文章的摘要。
    可见,摘要算法就是通过摘要函数f()对任意长度的数据data计算出固定长度的摘要digest,目的是为了发现原始数据是否被人篡改过。
    我们以常见的摘要算法MD5为例,计算出一个字符串的MD5值:

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

    计算结果如下:

    d26a53750bc40b38b65a520292f69306
    

    hmac

    通过哈希算法,我们可以验证一段数据是否有效,方法就是对比该数据的哈希值,例如,判断用户口令是否正确,我们用保存在数据库中的password_md5对比计算md5(password)的结果,如果一致,用户输入的口令就是正确的。
    为了防止黑客通过彩虹表根据哈希值反推原始口令,在计算哈希的时候,不能仅针对原始输入计算,需要增加一个salt来使得相同的输入也能得到不同的哈希,这样,大大增加了黑客破解的难度。

    itertools

    Python的内建模块itertools提供了非常有用的用于操作迭代对象的函数。
    首先,我们看看itertools提供的几个“无限”迭代器:

    >>> import itertools
    >>> natuals = itertools.count(1)
    >>> for n in natuals:
    ...     print(n)
    ...
    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']
    

    在Python中,读写文件这样的资源要特别注意,必须在使用完毕后正确关闭它们。正确关闭文件资源的一个方法是使用try...finally

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

    try...finally非常繁琐。Python的with语句允许我们非常方便地使用资源,而不必担心资源没有关闭,所以上面的代码可以简化为:

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

    并不是只有open()函数返回的fp对象才能使用with语句。实际上,任何对象,只要正确实现了上下文管理,就可以用于with语句。
    实现上下文管理是通过__enter____exit__这两个方法实现的。例如,下面的class实现了这两个方法:

    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)
    

    编写__enter____exit__仍然很繁琐,因此Python的标准库contextlib提供了更简单的写法,上面的代码可以改写如下:

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

    contextlib

    @contextmanager这个decorator接受一个generator,用yield语句把with ... as var把变量输出出去,然后,with语句就可以正常地工作了:

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

    @closing

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

    from contextlib import closing
    from urllib.request import urlopen
    
    with closing(urlopen('https://www.python.org')) as page:
        for line in page:
            print(line)
    

    urllib

    urllib提供了一系列用于操作URL的功能。

    get

    urllib的request模块可以非常方便地抓取URL内容,也就是发送一个GET请求到指定的页面,然后返回HTTP的响应:
    例如,对豆瓣的一个URLhttps://api.douban.com/v2/book/2129650进行抓取,并返回响应:

    from urllib import request
    
    with request.urlopen('https://api.douban.com/v2/book/2129650') 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'))
    

    可以看到HTTP响应的头和JSON数据:

    Status: 200 OK
    Date: Thu, 29 Nov 2018 03:14:04 GMT
    Content-Type: application/json; charset=utf-8
    Content-Length: 2138
    Connection: close
    Vary: Accept-Encoding
    X-Ratelimit-Remaining2: 99
    X-Ratelimit-Limit2: 100
    Expires: Sun, 1 Jan 2006 01:00:00 GMT
    Pragma: no-cache
    Cache-Control: must-revalidate, no-cache, private
    Set-Cookie: bid=eoWvbo5R3mg; Expires=Fri, 29-Nov-19 03:14:04 GMT; Domain=.douban.com; Path=/
    X-DOUBAN-NEWBID: eoWvbo5R3mg
    X-DAE-Node: anson74
    X-DAE-App: book
    Server: dae
    X-Frame-Options: SAMEORIGIN
    Data: {"rating":{"max":10,"numRaters":16,"average":"7.4","min":0},"subtitle":"","author":......}

    相关文章

      网友评论

          本文标题:常用内建模块2

          本文链接:https://www.haomeiwen.com/subject/usqtcqtx.html