
1.3.3 网络模块
Python提供了强大的模块支持,不仅有大量的标准模块,还有大量的第三方模块。开发者也可以开发自定义模块。这些强大的模块可以极大地提高开发者的开发效率。
模块就是Python程序,任何Python程序都可以作为模块。随着程序功能的复杂化,程序不断变大。为了便于维护,通常会将其分为多个文件(模块),这样不仅可以提高代码的可维护性,还可以提高代码的可重用性。当编写好一个模块后,若编程过程中需要用到该模块的某个功能(由变量、函数、类实现),则无须做重复性的编写工作,直接在程序中导入该模块即可。
(1)导入模块
Python中有几种方法可以导入模块。
●导入整个模块:import模块名,如导入sys模块,import sys。
●导入整个模块,并指定别名:import模块名as别名。

●导入模块中的某个或某些函数:from模块名import函数名。

●导入指定模块中的所有成员:from模块名import*。
(2)自定义模块
下面是创建自己的模块并将函数从一个模块导入另一个模块的例子。
首先,创建名为check_ip_func.py的文件,其功能是根据参数检查IP地址的正确性,返回IPv4Address或IPv6Address对象;默认情况下,小于232的整数将被视为IPv4地址。如果地址不是有效的IPv4或IPv6地址,则会引发ValueError。代码如下:

上面的代码可以独立运行,执行结果如下:

其次,将check_ip_func.py文件作为模块,供其他Python程序调用。在check_ip_func.py文件同一目录下,创建名为get_correct_ip.py文件,该文件将调用check_ip_func.py模块中定义的check_ip()函数,以从地址列表中选择正确的IP地址。


执行结果如下:

从上面的执行结果中可以看到,Python解释器将模块check_ip_func.py中的代码也一块儿执行了,执行结果中的前3行就是模块check_ip_func.py的执行结果,但这并不是我们想要的结果。
想要避免这种情况的关键在于,要让Python解释器知道,当前要运行的程序是模块本身,还是导入模块的其他程序。在模块check_ip_func.py中,仅仅定义函数,不需要其他的代码,修改后的代码如下:

而get_correct_ip.py程序保持不变,在执行get_correct_ip.py后即可得到我们想要的结果:

下面将介绍常用的3个网络编程模块:ipaddress模块、netaddr模块和tabulate模块。
(1)ipaddress模块
该模块包括IPv4和IPv6地址的类,可以用来生成、验证、查找IP地址。从Python 3.3开始,ipaddress模块正式成为Python标准库中的模块之一,不需要安装,可直接使用。
ipaddress模块中有IPv4Address类和IPv6Address类,可分别用来处理IPv4和IPv6地址。由于IPv4Address和IPv6Address对象共享许多共同属性,下面的案例将只处理IPv4格式,可以以类似的方式处理IPv6格式。
●ipaddress.ip_address()函数会根据传入的字符串自动创建IPv4/IPv6 Address对象。

也可以使用正整数来创建地址,默认小于232的整数是IPv4地址,大于232的整数则是IPv6地址。

使用ipaddress.ip_address()创建IPv4Address对象有很多IPv4地址的属性。

●使用ipaddress.ip_network()函数创建IPv4/IPv6Address对象。

ipaddress.ip_network()函数允许划分网络(子网划分)。默认情况下,它将网络划分为两个子网。

通过prefixlen_diff参数设置允许指定子网的位数。

●ipaddress.ip_interface()函数允许创建IPv4或IPv6接口对象。

(2)netaddr模块
该模块是Python处理IP地址和MAC地址的开源第三方库,是用于对网络地址段进行定义和操作的一个工具类。通过netaddr模块可以以非常灵活的方式定义网段,获取网段的一些常用信息,同时可以和网络地址与网段进行一些包含关系的运算。
netaddr模块不是Python的标准模块,使用前需要安装。

●IPAddress对象表示单个IP地址,可以接收一个IPv4或IPv6地址字符串。

●IPNetwork()是处理IP网段的方法,同样可以接收一个IPv4或IPv6地址字符串。

●cidr_merge()是网段的汇总方法,它只接收列表,列表中必须含有要汇总的网段。

●EUI()是netaddr格式化MAC地址的方法,可以接收任何表达形式的MAC地址字符串。

(3)tabulate模块
通过tabulate模块可以精美地显示数据。它不是Python标准库,因此需要先进行安装。

●tabulate模块支持列表、字典等表格数据类型。模块中的tabulate()函数用于制表。

●tabulate()函数还可以使用headers参数指定列名。

●tabulate()函数还可以使用参数tablefmt输出网格。
