模块是包括 Python 定义和声明的文件。文件名就是模块名加上 .py 后缀。可以由全局变量__name__得到模块的模块名(一个字符串)。默认模块可以通过help()-->modules名称查看。

模块示例:

"""
Bars Module
============
这是一个打印不同分割线的示例模块
"""
def starbar(num):
    """打印 * 分割线

    :arg num: 线长
    """
    print('*' * num)

def hashbar(num):
    """打印 # 分割线

    :arg num: 线长
    """
    print('#' * num)

def simplebar(num):
    """打印 - 分割线

    :arg num: 线长
    """
    print('-' * num)

对模块的应用如下

>>> import bars	#引入模块
>>>
>>> bars.hashbar(10)	# 调用模块函数
##########
>>> bars.simplebar(10)
----------
>>> bars.starbar(10)
**********
>>>
>>> from bars import simplebar, starbar	#从模块中导出特定模块
>>> simplebar(20)
>>>
>>> from module import * 	# 导入模块中的所有定义
>>>
--------------------

含有__init__.py文件的目录可以用来作为一个包,目录里的所有 .py 文件都是这个包的子模块。

$ tree mymodule                                                                
mymodule
|-- bars.py
|-- __init__.py
|-- utils.py

0 directories, 3 files

mymodule 是一个包名并且 bars 和 utils 是里面的两个子模块。

几大常用模块

os模块

os 模块提供了与操作系统相关的功能。

>>> import os	# 引入模块
>>> os.getuid()	# getuid() 函数返回当前进程的有效用户 id
500
>>> os.getpid()	# getpid() 函数返回当前进程的 id
16150
>>> os.getppid()	# getppid() 返回父进程的 id
14847
>>> os.uname()	# uname() 函数返回识别操作系统的不同信息,在 Linux 中它返回的详细信息可以从 uname -a 命令得到。uname() 返回的对象是一个元组,(sysname, nodename, release, version, machine)。
('Linux', 'd80', '2.6.34.7-56.fc13.i686.PAE', '#1 SMP Wed Sep 15 03:27:15 UTC 2010', 'i686')
>>> os.getcwd()	# getcwd() 函数返回当前工作目录
'/home/shiyanlou'
>>> os.chdir('Code')	# chdir(path) 则是更改当前目录到 path
>>> os.getcwd()
'/home/shiyanlou/Code'

所以现在让我们使用 os 模块提供的另一个函数来创建一个自己的函数,它将列出给定目录下的所有文件和目录。

def view_dir(path='.'):
    """
    这个函数打印给定目录中的所有文件和目录
    :args path: 指定目录,默认为当前目录
    """
    names = os.listdir(path)
    names.sort()
    for name in names:
        print(name, end =' ')
    print()

具体使用情况

>>> view_dir('/')
.bashrc .dockerenv .profile bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var

Requests模块

Requests 是一个第三方 Python 模块。第三方模块并不是默认的模块,意味着你需要安装它,我们使用 pip3 安装它。

$ sudo apt-get update
$ sudo apt-get install python3-pip	# 安装 pip3
$ sudo pip3 install requests	# 用 pip3 安装 requests
获得一个简单的网页

你可以使用 get() 方法获取任意一个网页。

>>> import requests
>>> req = requests.get('https://github.com')
>>> req.status_code
200

req 的 text 属性存有服务器返回的 HTML 网页,由于 HTML 文本太长就不在这里贴出来了。

使用这个知识,让我们写一个能够从指定的 URL 中下载文件的程序。

#!/usr/bin/env python3
import requests

def download(url):
    '''
    从指定的 URL 中下载文件并存储到当前目录
    url: 要下载页面内容的网址
    '''
    # 检查 URL 是否存在
    try:
        req = requests.get(url)
    except requests.exceptions.MissingSchema:
        print('Invalid URL "{}"'.format(url))
        return
    # 检查是否成功访问了该网站
    if req.status_code == 403:
        print('You do not have the authority to access this page.')
        return
    filename = url.split('/')[-1]
    with open(filename, 'w') as fobj:
        fobj.write(req.content.decode('utf-8'))
    print("Download over.")

if __name__ == '__main__':
    url = input('Enter a URL: ')
    download(url)

if __name__ == '__main__':这条语句的作用是,只有在当前模块名为__main__的时候(即作为脚本执行的时候)才会执行此 if 块内的语句。换句话说,当此文件以模块的形式导入到其它文件中时,if 块内的语句并不会执行。

Collections模块

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

Counter类

Counter 是一个有助于 hashable 对象计数的 dict 子类。它是一个无序的集合,其中 hashable 对象的元素存储为字典的键,它们的计数存储为字典的值,计数可以为任意整数,包括零和负数。

>>> from collections import Counter
>>> import re

# 查看 Python 的 LICENSE 文件中某些单词出现的次数。
>>> path = '/usr/lib/python3.5/LICENSE.txt'
>>> words = re.findall('\w+', open(path).read().lower())
>>> Counter(words).most_common(10)
[('the', 80), ('or', 78), ('1', 66), ('of', 61), ('to', 50), ('and', 48), ('python', 46), ('in', 38), ('license', 37), ('any', 37)]

# Counter 对象有一个叫做 elements() 的方法,其返回的序列中,依照计数重复元素相同次数,元素顺序是无序的。
>>> c = Counter(a=4, b=2, c=0, d=-2)
>>> list(c.elements())
['b','b','a', 'a', 'a', 'a']

# most_common() 方法返回最常见的元素及其计数,顺序为最常见到最少。
>>> Counter('abracadabra').most_common(3)
[('a', 5), ('r', 2), ('b', 2)]
defaultdict类

defaultdict 是内建 dict 类的子类,它覆写了一个方法并添加了一个可写的实例变量。其余功能与字典相同。defaultdict() 第一个参数提供了 default_factory 属性的初始值,默认值为 None,default_factory 属性值将作为字典的默认数据类型。所有剩余的参数与字典的构造方法相同,包括关键字参数。

同样的功能使用 defaultdict 比使用 dict.setdefault 方法快。

>>> from collections import defaultdict
>>> s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
>>> d = defaultdict(list)
>>> for k, v in s:
...     d[k].append(v)
...
>>> d.items()
dict_items([('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])])

即使 defaultdict 对象不存在某个键,它会自动创建一个空列表。

namedtuple类

命名元组有助于对元组每个位置赋予意义,并且让我们的代码有更好的可读性和自文档性。你可以在任何使用元组地方使用命名元组。在例子中我们会创建一个命名元组以展示为元组每个位置保存信息。

>>> from collections import namedtuple
>>> Point = namedtuple('Point', ['x', 'y'])  # 定义命名元组
>>> p = Point(10, y=20)  # 创建一个对象
>>> p
Point(x=10, y=20)
>>> p.x + p.y
30
>>> p[0] + p[1]  # 像普通元组那样访问元素
30
>>> x, y = p     # 元组拆封
>>> x
10
>>> y
20