后端编程Python3-标准库概览

内容分享3周前发布
0 0 0

本节是第五讲的第十二小节,上节为大家介绍了模块与包的概念,本节将为大家介绍标准库一些常用模块。

Python标准库概览(Overview of Python's Standard Library)

Python标准库一般被描述为”自带的电池”,自然地提供了广泛的功能,涵盖了大致200个左右的包与模块。

实际上,近年来,大量可用于Python的高质量模块被开发出来,如果将所有这些模块都包含在标准库中可能会使得Python发布包大小提高至少一个数量级。因此,标准库中的那些模块在更多的意义上是对Python历史及其核心开发人员兴趣的一种折射,而并不是表明要系统化地去创建一个“均衡的”标准库。并且,有些模块已经被证实放置在标准库中极难维护——最著名的就是Berkeley DB模块——因此被清理出标准库,并进行单独维护。这意味着,Python有许多可用的、优秀的第三方模块—— 尽管这些模块有很高的质量,并且很有用一仍不在标准库中。

在本节中,我们对其所提供的功能进行了宽广的概览,釆用的是主题化的方法, 但没有讲述那些特别专业化的模块以及那些特定于某种平台的模块。在许多情况下, 提供了小实例,以便对包与模块有直观的了解。此外,对那些在书中其他位置处展示的包与模块,给出了其交叉索引。

字符串处理(String Handling)

String 模块提供了一些有用的常量,列如 string.ascii_letters 与 string.hexdigits。该模块还提供了 string.Formatter类,我们可以实现该类的子类,以便提供自定义的字符串格式化器。textwrap模块可用于捕获指定宽度的文本行,并最小化缩排的需求。

Struct模块提供了一些函数,可用于将数字、布尔型变量以及字符串打包为字节对象(以其二进制表明形式),或从字节对象中拆分为适当的类型。在需要对数据进行处理,使其发送到以C语言编写的底层库(或从其中接收数据)时,这是弃用的。

difflib模块提供了用于对序列(列如字符串)进行比较的类与方法,并可以产生以标准的”diff”格式与HTML格式表明的输出信息。

Python中功能最强劲的字符串处理模块是re(正则表达式)模块,io.StringlO类可以提供类似于字符串的对象,其行为与内存中的文本文件类似。 如果我们需要使用与写入文件一样的代码来写字符串,那么使用该类会提供许多便利。

io.StringIO 类

Python提供了两种将文本写入到文件的不同方法,一种是使用文件对象的write()方法,另一种是使用print()函数,并将其关键字参数file设置为打开并等待写入的文件对象,列如:

print(“An error message”, file=sys.stdout)

sys.stdout.write(“Another error message
“)

上面两行文本都将被打印到sys.stdout,这是一个文件对象,表明“标准输出流”——这一般是控制台,不同于sys.stderr (“错误输出流”),区别仅在于后者是非缓冲的。(在程序启动时,Python自动创建并打开sys.stdin、sys.stdout与sys.stderr) 默认情况下,print()函数会添加一个新行,我们可以通过将关键字参数end设置为空字符串来阻止这一点。

有些情况下,将本来要写入到文件中去的输出信息捕获到字符串中是有用的,这可以使用io.StringlO类实现,该类提供的对象可以像文件对象一样使用,但其中以字符串来存放写入其中的任何数据。如果对io.StringlO对象赋予一个初始字符串,就可以像对文件一样进行读取。

如果已执行import io,就可以存取io.StringIO,并用其捕获本来要输入到文件对象(列如sys.stdout)中的输出信息:

sys.stdout = io.StringIO()

如果将上面一行代码放置在程序的起始处,那么在导入之后与使用sys.stdout 之前,发送给sys.stdout的任意文本实际上都将发送给io.StringlO,这是该行代码创建的一个类似于文件的对象,并且该对象替换了标准的sys.stdout文件对象。目前, 当前面展示的print()与sys.stdout.write()执行后,其输出将输出到io.StringlO对象, 而非控制台(任意时刻,我们都可以使用语句sys.stdout = sys.__stdout__来恢复原始的 sys.stdout)。

通过调用io.StringIO.getvalue()函数,我们可以获取所有写入到io.StringlO对象的字符串,这里具体调用的是sys.stdout.getvalue() 其返回值是一个字符串,其中包含已经写入的所有行。该字符串可以打印出来,或者保存到日志中,或通过网络连接发送——就像任何其他字符串一样。

命令行程序设计(Command-Line Programming)

如果我们需要处理那些在控制台中被重定向的文本,或那些包含在命令行中列出的文件中的文本,那么可以使用fileinput模块的fileinput.input()函数,该函数会对控制台中重定向的所有行(如果存在)进行迭代,或对命令行中列出的文件中的所有行进行迭代,就像对一个连续的行序列一样。通过使用fileinput.filename()与fileinput. lineno(),该模块可以在任意时刻报告当前文件名与行号。

optparse模块

optparse,是一个更够让程序设计人员轻松设计出简单明了、易于使用、符合标准的Unix命令例程式的Python模块。生成使用和协助信息。程序中使 用optparse模块来处理命令行参数,而不再使用自定义函数:

def main():

parser = optparse.OptionParser()

parser. add_option(“-w”,”–maxwidth”, dest=”maxwidth”, type=”int”, help=(“the maximum number of characters that can be” “output to string fields [default: %default]”))

parser.add_option(“-f”, “–format”, dest=”format”,help=(“the format used for outputting numbers ” “[default: %default]”))

parser.set_defaults(maxwidth=100, format=”.0f”)

opts, args = parser.parse_args()

包括import optparse语句,该函数只需要使用9行代码。而且,我们不需要显式地提供-h与-help选项,这些是由optparse模块处理的,该模块使用来自关键字参数help中的文本,并生成适当的使用协助信息,并用默认值替换”%default”文本。

还要注意的是,选项目前使用的是常规的UNIX风格,同时包含长选项名与短选项名,选项名以连线符引导。在控制台上交互式使用时,短选项名是方便的;在shell脚本中使用时,使用长选项名则更易于理解。列如,为将最大宽度设置为80,可以使用-w80、 -w 80、-width=80或–width 80中的任何一种语法指定。对命令行进行分析后,这些选项名可以通过dest名称进行访问,列如opts.maxwidth与opts.format,而任何尚未处理的命令行参数(一般是文件名)则存在于args列表中。

如果分析命令行时出错,那么optparse分析器将调用sys.exit(2),这会使得该程序干净地终止,并将2作为程序的结果值返回给操作系统。常规上,返回值为2表明使用错误,1表明任意其他类型的错误,0则代表成功。不带参数调用sys.exit()时,将向操作系统返回0。

数学与数字(Mathematics and Numbers)

除内置的int、float与complex之外,标准库还提供了 decimaLDecimal与 fractions.Fraction这两种数据类型。有3个可用的数值型标准库:math用于标准的数学函数;cmath用于复数数学函数;random提供了许多用于随机数生成的函数。这些模块在第2章中进行了介绍。

Python的数值型抽象基类(指那些可以被继承,但不能直接使用的类)是在numbers 模块中定义的,该基类在检测某个对象的具体类型时是有用的,列如,对象x, isinstance(x, numbers.Number)可以检测 x 是否是任何一种类型的数字,isinstance(x, numbers.Rational) 与isinstance(x, numbers.Integral)则可以检测x是否是某种特定类型的数据。

如果需要进行科学与工程计算,那么第三方包NumPy是有用的。该模块提供了 超级高效的n维数组,基本的线性代数函数与傅里叶变换函数,以及用于整合C、C++ 与Fortran代码的工具。SciPy包整合了 NumPy,并对其进行了扩展,使其包含用于统计学计算、信号与图像处理、遗传算法以及许多其他运算的模块。两个包都可以在 www.scipy.org处免费获取。

时间与日期(Times and Dates)

calendar模块与datetime模块提供了用于处理日期与时间的函数。不过,这两个模块都是基于理想化的罗马日历,因此不适合处理罗马日历之前的日期。日期与时间处理是一个超级复杂的主题——不同地点与不同时间使用的日历都是可变的,一天并不是准确的24小时,一年也不是准确的365天,夏令时与时区也都是可变的。 datetime.datetime类(不是datetime.date类)提供了一些处理时区的相关规定,但并不 是直接可以这样用,好在第三方模块可以弥补这一不足,列如
www.labix.org/python-dateutil 提供的 dateutil, 以及
www.egenix.com/products/python/mxBase/mxDate Time 提供的 mxDateTime。

time模块可以处理时间戳,时间戳实际上是数字,其中存放的是自初始时间(在UNIX上为1970-01-01 00:00:00)至今经过的秒数。该模块可用于获取以UTC (协调世界时)格式表明的机器当前时间,或夏令时形式的本地时间,也可以创建日期、时间以及多种格式的日期/时间字符串,也可以用于分析包含日期与时间的字符串。

实例:calendar, datetime 与 time模块

datetime.datetime类型的对象一般是由程序创建的,存放UTC日期/时间的对象则一般是从外部接收的,列如文件的时间戳,下面给出一些实例:

import calendar, datetime, time

moon_datetime_a = datetime.datetime(1969, 7, 20, 20, 17, 40)

moon_time = calendar.timegm(moon_datetime_a.utctimetuple())

moon_datetime_b = datetime.datetime.utcfromtimestamp(moon_time)

moon_datetime_a.isoformat() # returns: '1969-07-20T20:17:40'

moon_datetime_b.isoformat() # returns: '1969-07-20T20:17:40'

time.strftime(“%Y-%m-%dT%H:%M:%S”, time.gmtime(moon_time))

moon_datetime_a变量为datetime.datetime类型,其中存放的是Apollo 11的登月时间。moon_time是int变量,其中存放的是登月时间至今经过的秒数——该数值是由 calendar.timegm()函数提供的,该函数接受由
datetime.datetime.utctimetuple()函数返回的time_struct对象作为参数,并返回time_struct表明的秒数。(由于登月时间早于UNIX初始时间,因此该数值是一个负数) moon_datetime_b变量类型为datetime.datetime,是根据moon_time整数创建的,以便展示从秒数(自初始时间至今)到datetime.datetime 对象的转换,最后三行代码返回的是等价的但以ISO 8601格式表明的日期/时间字符串。

当前的UTC日期/时间可以作为一个datetime.datetime对象,并通过调用 datetime.datetime.utcnow()函数获取,也可以作为自初始时间至今的秒数,通过调用 time.time()获取。对本地的日期/时间,则可以调用datetime.datetime.now()或time.mktime (time.localtime())。

算法与组合数据类型(Algorithms and Collection Data Types)

bisect模块提供的函数可用于搜索有序序列,列如有序列表,也可以用于向其中插入项,同时又保证序列的有序性。heapq模块提供的函数可以将序列(列如列表) 转换为堆–一种组合数据类型,其中第一项(索引位置为0)总是最小的,也可以用于向其中插入或移除项,同时又保证序列依旧是一个堆。

collections 包提供了字典 collections.defaultdict 与组合数据类型 collections.named-tuple.

前面已经有所讨论。此外,该包还提供了 collections.UserList与collections.UserDict等数据类型,尽管对内置的list与dict类型进行子类化可能比使用这两种类型更常见。另 —种类型是collections.deque,该类型与list类似,差别在于,在列表的结尾处添加或移除项有很快的速度,collections.deque则在开始处与结尾处添加或移除项都有很快的速度。

Python 3.1 引入了 collections.OrderedDict 和 collections.Counter 类。OrderedDict 具有有正常dicts一样的API,尽管在对字典项目进行迭代式,这些项目总是以插入顺序返回(例如,从第一个到最后一个插入),而且popitem()方法总是返回最近被添加的项目(列如last)。Counter类是dict的一个子类,它提供了一种保持各种计数的便捷而且快速的方法。例如,假定目前有一个iterable或映射(例如一个字典),Counter 实例可以以(元素,个数)二元组的形式返回唯一元素或最常见元素的列表。

Python的非数值型抽象基类(指那些可以被继承,但不能直接使用的类)也在 collections包中提供。

array模块提供了序列类型array.array,可以以超级节省空间的方式存储数单词或字符。该类型与列表的行为类似,区别在于其中可存放的对象类型是固定的(创建时), 因此,这种类型不能像列表那样存放不同类型的对象。前面提及的第三方包NumPy也可以提供高效的数组。

weakref模块提供了创建弱引用的功能——与一般的引用类似,区别在于,如果对某个对象仅有的引用是弱引用,那么该对象依旧可以被调度进入垃圾收集,这可以防止某些对象仅仅由于存在对其的引用而保存在内存中。我们可以检测对某个对象的弱引用是否存在,如果存在,就可以访问该对象。

实例:heapq模块

heapq模块提供了将列表转换为堆的功能,也可以用于对堆中添加或删除项,同时又保证堆特性。堆实际上是一个二元树,并遵守堆特性——也即第一项(索引位置 0)总是最小项。堆的每个子树也是一个堆,因此也遵守堆特性。下面展示了如何从头开始创建一个堆:

import heapq

heap = []

heapq.heappush(heap, (5, “rest”))

heapq.heappush(heap. (2, “work”))

heapq.heappush(heap, (4, “study”))

如果已有某个列表,就可以使用heapq.heapify(alist)将其转换为堆,该函数可以自动完成必要的重新排序。使用heapq.heappop(heap)可以从堆中移除最小项。

for x in heapq.merge([1, 3, 5, 8], [2, 4, 7], [0, 1, 6, 8, 9]):

print(x, end=” “) # prints: 0 1 1 2 3 4 5 6 7 8 8 9

heapq.merge()函数以任意数量的排序后iterables作为参数,并返回一个迭代子, 该迭代子对iterables依序指定的所有项进行迭代。

文件格式、编码与数据持久性(File Formats,Encodings,and Data Persistense)

标准库提供了对大量标准文件格式与编码的广泛支持。base64模块提供的函数可以读写RFC 3548中指定的Base16、Base32与Base64等编码格式。quopri模块提供的函数可以读写”quoted-printable”格式,该格式在RFC 1521中定义,并用于MIME (多用途Internet邮件扩展)数据。uu模块提供的函数可以读写uuencoded数据。RFC 1832 定义了外部数据表明标准,xdrlib模块提供的函数可以读写这种格式。

还有些模块提供了对釆用最流行的格式的存档文件的读写功能。bz2模块可以处理.bz2文件,gzip模块可以处理.gz文件,taffile模块可以处理.tar、.tar.gz (也即.tgz) 与.tar.bz2文件,zipfile模块可以处理.zip文件。我们将在这一小节中查看一个使用tarfile 模块的实例,后面提供了一个使用gzip模块的小实例。

对某些音频格式数据的处理功能也在某些模块中实现,列如,aifc模块可以处理 AIFF (音频交换文件格式),wave模块可以处理(未压缩的).wav文件。有些音频数据格式可由audioop模块进行操纵,sndhdr模块提供了两个函数,可用于确定文件中 存放的是哪种类型的音频数据以及某些特性,列如釆样率。

RFC 822中定义了一种配置文件(类似于老格式的Windows .ini文件)格式, configparser模块提供了用于读写这种文件格式的函数。

许多应用程序(列如Excel)可以读写CSV (逗号分隔值)数据,或某些变种格 式,列如制表符分隔的数据。csv模块可以读写这些格式,并可以防止CSV文件被直接处理。

除了对多种文件格式的支持外,标准库中还有一些包与模块提供了对数据持久性的支持。pickle模块用于向磁盘中存储或从磁盘中取回任意的Python对象(包括整个组合)。标准库也支持各种类型的DBM文件——类似于字典,差别在于其项存储在磁盘中,而非内存中,并且其健与值都必须是bytes对象或字符串。shelve模块可以提供DBM文件,其健为字符串,值为任意的Python对象 该模块在幕后无缝实现了 Python对象与bytes对象之间的转换。

实例:ase64模块

在对以ASCII文本嵌入在电子邮件中的二进制数据进行处理时,base64模块的使用最为广泛。该模块也可以用于将二进制数据存储到.py文件中。第一步是将二进制数据转换为Base64格式,这里假定已导入base64模块,并且.png文件的路径与文件名存放在变量left_align_png中:

binary = open(left_align_png,“rb”).read()

ascii_text =””

for i, c in enumerate(base64.b64encode(binary)):

if i and i % 68 == 0:

ascii_text += “\

ascii_text += chr(c)

后端编程Python3-标准库概览

这一代码段以二进制模式读入文件,并将其转换为一个由ASCII字符组成的 Base64编码字符串。每隔68个字符添加一个反斜线与换行符,将每行的ASCII字符宽度限制为68,但要保证在读回数据时忽略换行符(由于反斜线将对其进行转义)。 以这种方式获取的ASCII文本可以在.py文件中存储为字面意义的bytes,列如:

LEFT_ALICN_PNC = b””” iVBORwOKCgoAAAANSUhEUgAAACAAAAAgCAYAAABzenrOAAAABCdBTUEAALCPC/xhBQAA

bmquu8PAmVT2+CwW6rCyA9UfFMCkl+bN6pl8tCWqcUzrDOwBh2zVCR+jZVeAAAAAEIF

TkSuQmCC”””

我们忽略了大多行,并使用省略号表明。

使用下面的语句,可以将数据转换为原始的二进制格式。

binary = base64.b64decode(LEFT_ALIGN_PNG)

二进制数据可以使用open(filename, “wb”).write(binary)写入到文件中。在py文件中,以二进制格式保存要比以原始格式保存更加紧凑。需要提供一个程序,该程序需要使用保存在单独的.py文件中的二进制数据时,使用二进制格式是有用的。

文件、目录与进程处理(File、Directory、and Process Handling)

Shutil模块提供了用于文件与目录处理的高层函数,包括用于复制文件与整个目录的shutil.copy()函数与shutil.copytree()函数,用于移动目录树的shutil.move()函数, 以及用于移动整个目录树(包括非空的)的shutil.rmtree()函数。

临时文件与目录应该使用tempfile模块创建,该模块提供了必要的函数,列如 tempfile.mkstemp(),并以尽可能安全的方式创建临时对象。

filecmp模块可用于对文件进行比较(使用filecmp.cmp()函数),也可以用于对整个目录进行比较(使用filecmp.cmpfiles()函数)。

Python程序一种超级强劲而有效的用法是调度其他程序的运行,这可以使用subprocess模块完成,该模块可以调度其他进程,使用管道在其间进行通信,并取回其结果。一种更有效的替代方案是使用multiprocessing模块,该模块提供了广泛的工具,可用于将工作载荷分布到多个进程,并可以累积结果, 一般可用于替代多线程。

os模块提供了对操作系统功能的访问接口,并且是平台无关的。os.environ变量存放的是映射对象,其项为环境变量名及其值。程序的工作目录可由os.getcwd()提供, 并可以使用os.chdir()修改。该模块还提供了一些函数,可用于实现底层基于文件描述符的文件处理。os.access()函数可用于确定某个文件是否存在,或者文件是否可读/可写;os.listdir()函数可以返回给定目录中的条目列表(列如,文件与目录,但排除.条目与..条目);os.stat()函数返回关于文件与目录的各种信息项,列如模式、访问时间与大小等。

目录可以使用os.mkdir()创建,或者,如果需要创建中间目录就使用os.makedirs()。 空目录可以使用os.rmdir()移除,只包含空目录的目录树可以使用os.removedirs()移除。 文件与目录都可以使用os.remove()移除,也可以使用os.rename()重命名。

os.walk()函数可以在整个目录树上进行迭代,依次取回每个文件与目录的名称。

os模块也提供了许多底层的平台特定的函数,列如,操纵文件描述符的函数,以及fork (仅适用于UNIX系统)、spawn与exec等。

os模块提供的函数主要是与操作系统进行交互,尤其对文件系统,os.path模块则提供了字符串(路径)操纵函数与便于操纵文件系统的函数的混合。os.path.abspath() 函数可以返回其参数的绝对路径,并移除冗余的路径分隔符与..元素;os.path.split()函数返回一个二元组,其中第一项包含路径,第二项则是文件名(如果某个路径中没有文件名,此项就为空),这两项也可以直接使用os.path.basename()与os.path.dirname()获取。文件名也可以分为两个部分,即名称与扩展名,这是使用os.path.splitext()实现 的。os.path.join()函数可以接受任意数量的路径字符串,并使用平台特定的分隔符返回单一的路径。

如果需要获取某个文件或目录的多项信息,就可以使用os.stat(),但是如果只需要某种单一的信息,就可以使用相关的os.path函数,列如,os.path.exists()、os.path.getsize()、 os.path.isfile()或 os.path.isdir()。

mimetypes模块包含mimetypes.guess_type()函数,可用于猜测给定文件的MIME类型。

实例:os模块与os.path模块

下面展示了如何使用os模块与os.path模块来创建字典,其中每个键是一个文件名(包括其路径),每个值则为文件最后依次修改时的时间戳(自初始时间至今的秒数), 这些文件都在给定的path中:

date_from_name = {}

for name in os.listdir(path):

fullname = os.path.join(path, name)

if os.path.isfile(fullname):

date_from_name[fullname] = os.path.getmtime(fullname)

这段代码是超级直接的,但是只能用于单一目录中的文件。如果需要在整个目录树中进行操作,那么可以使用os.walk()函数。

下面给出从finddup.py程序中提取的代码段,这段代码创建了一个字典,每个键都是一个二元组(文件大小,文件名),其中文件名不包含路径,每个值则是一个列表, 其中包含了与键的文件名匹配并具有同样文件大小的所有文件名。

data = collections.defaultdict(list)

for root, dirs, files in os.walk(path):

for filename in files:

fullname = os.path.join(root, filename)

key = (os.path.getsize(fullname), filename)

data[key].append(fullname)

对每个目录,os.walk()返回root与两个列表,一个是目录中的所有子目录,另一个是目录中的文件。为获取某个文件名的完整路径,我们只需要结合root与文件名。 需要注意的是,我们不需要自己递归到子目录中——os.walk()会做到这一点。在数据收集完毕后,我们就对其进行迭代,并生成一个关于可能的重复文件的报告:

for size, filename in sorted(data):

names = data[(size,filename)]

if len(names) > 1:

print(“{filename} ({size} bytes) may be duplicated”

“({0} files):”.format(len(names), **locals()))

for name in names:

print(” {0}”.format(name))

由于字典的键是元组(文件大小,文件名),因此我们不必使用key函数来获取以大小排序的数据。如果任意的(文件大小,文件名)元组在其列表中包含多于一个文件名,就可能存在重复。

shell32.dll (8460288 bytes) may be duplicated (2 files):

windowssystem32shell32.dll

windowssystem32dllcacheshell32.dll

上面给出的是在Windows XP系统上运行finddup.py windows后,从其3282输出信息中提取的最后一项。

网络与Internet程序设计

用于网络与Internet程序设计的包与模块是Python标准库的主要组成部分。在最底层,socket模块提供了大多数基本的网络功能,包括用于创建socket的函数、用于进行DNS (域名系统)查询的函数以及处理IP (Internet协议)地址的函数等。加密与认证的socket则可以使用ssl模块建立。socketserver模块提供了TCP (传输控制协议)服务器与UDP (用户数据报协议)服务器,这些服务器可以直接处理请求,也可以创建单独的进程(通过forking)或单独的线程来分别处理每个请求。异步的客户端与服务器socket处理可以使用asyncore模块以及构建在其上的更高层的asynchat模块来实现。

Python定义了 WSGI(Web服务器网关接口),旨在为Web服务器以及Python 编写的应用程序之间提供一个标准接口。在对标准的支持方面,wsgiref包提供了 WSGI的参考实现,包括提供WSGI兼容的HTTP服务器的模块,以及用于处理响应头与CGI (通用网关接口)脚本的模块。此外,http.server模块提供了一个 HTTP服务器,可以对其赋予一个请求处理者(提供了一个标准的),以便运行CGI脚本。

http.cookies模块与http.cookiejar模块提供了用于管理cookies的函数,CGI脚本支持则是由cgi模块与cgitb模块提供的。

客户端的HTTP请求是由http.client模块提供的,尽管更高层的urllib包中的模块urllib.parse、urllib.request、urllib.response、 urllib.error 以及 urllib.robotparser 等提供了更简单也更方便的对URL的访问。从Internet中抓取一个文件是很简单的, 如下所示:

fh = urllib.request.urlopen(“http://www.python.org/index.html”)

html = fh.read().decode(“utf8”)

urllib.request.urlopen()函数返回一个对象,该对象在行为上类似于一个以二进制读模式打开的文件对象。这里,我们取回的是Python Web站点的index.html文件(作为 一个bytes对象),并将其作为字符串存储在html变量中。使用
urllib.request.urlretrieve() 函数抓取文件并将其保存在本地文件中也是可能的。

HTML与XHTML文档可以使用html.parser模块进行分析,URL可以使用 urllib.parse模块创建与分析,robots.txt文件可以使用urllib.robotparser模块进行分析, 使用JSON (JavaScript对象表明法)表明的数据可以使用json模块进行读写。

除对HTTP服务器与客户端的支持外,标准库还提供了对XML-RPC (远程过程调用)的支持,这是使用xmlrpc.client模块与xmlrpc.server模块实现的。此外,还有一些附加的客户端功能,列如,由ftplib模块提供的FTP (文件传输协议)功能,由 nntplib模块提供的NNTP (网络新闻传输协议)功能,以及由telnetlib模块提供的TELNET功能。

smtpd模块提供了一个SMTP(简单邮件传输协议)服务器,在email客户端模块 中,smtplib 用于 SMTP, imaplib 用于 IMAP4 (Internet 消息访问协议),poplib 用于 POP3 (邮局协议)。各种格式的Mailboxes可以使用mailbox模块进行访问。单独的消息(包括多个部分组成的消息)可以使用email模块创建并操纵。

如果感觉标准库的包与模块尚不足以提供足够的网络功能,那么可以参考Twisted (www.twistedmatrix.com)提供的全面的第三方网络库。还有许多可用的Web程序库, 包括用于创建 Web 应用程序的 Django (www.djangoprqject.com)与 Turbogears (www. turbogears.org), Plone (www.plone.org)与 Zope (www.zope.org)则提供了完全的 Web 框架与内容管理系统。所有这些库都是使用Python实现的。

XML

在分析XML文档时,有两种广泛釆用的方法。一种是D0M (文档对象模型), 另一种是SAX (用于XML的简单API)。标准库提供了两个D0M分析器,一个是由 xml.dom模块提供的,另一个是由xml.dom.minidom模块提供的。SAX分析器则只有 xml.sax模块提供的一个。

我们已经使用了 xml.sax.saxutils模块中的xml.sax.saxutils.escape()函数(用于对“&”、”<”与“>”等字符进行XML转义),还有一个xml.sax.saxutils. quoteattr()函数可以实现类似的功能,并且附加地对引号进行转义(使得文本适合某个标签的属性),xml.sax.saxutils.unescape()函数则进行相反的转换。

还有一些其他可用的分析器。xml.parsers.expat模块可用于分析带expat的XML文档,前提是expat库是可用的;xml.etree.ElementTree可用于分析使用某种字典列表接口的XML文档。(默认情况下,DOM与元素树本身在底层使用expat分析器。)

手动写XML、使用DOM与元素树写XML,以及使用DOM、SAX与元素树分 析器分析XML

也存在一个第三方库lxml (www.codespeak.net/lxml),该库声称是“在Python 语言中,用于处理XML和HTML的功能最丰富,而且最容易使用的库”。该库提供 了一个接口,以及许多附加的功能(列如对Xpath、XSLT和许多其他XML技术的支持),其中该库提供的这个接口实际上是元素树模块提供的接口的超级。

实例:xml.etree.ElementTree 模块

Python的DOM与SAX分析器提供了一些API,熟练的XML程序员应该常常使用,xml.etree.ElementTree模块提供了一种更Python化的方法来对XML进行分析与写入。元素树模块添加到标准库是最近的事情,因此有些读者可能还不熟悉。鉴于此, 我们将在这里给出一个超级短小的实例以便对其有一个初步的了解,并对使用D0M与SAX的实现代码进行比较。

美国政府的NOAA (国家海洋与大气管理)的Web站点提供了涵盖范围很广的数据,包括一个XML文件,其中列出了 U.S.的气象站,该文件超过20 000行,包含了近2000个气象站的详细信息,下面是其中一个典型的条目:

<station>

<station_id>KBOS</stationJd>

<state>MA</state>

<station_name>Boston, Logan International Airport</station_name>

<xml_url>http://weather.gov/data/current_obs/KBOS.xml</xml_url>

</station>

我们已经剪切了一些行,并降低了文件中的大量缩排。该文件大致840KB,因此我们使用gzip将其压缩到易于管理的72KB。遗憾的是,元素树分析器或者需要一个文件名,或者需要一个文件对象,才可以进行读取,但我们不能将压缩后的文件提交给分析器处理,由于压缩后文件看起来就是一些随机的二进制数据。为此,我们使用两个初始的步骤来解决这一问题:

binary = gzip.open(filename).read()

fh = io.StringlO(binary.decode(“utf8”))

gzip模块的gzip.open()函数类似于内置的open()函数,区别在于可以读取gzip压缩的文件(以扩展名.gz结尾的文件),将其作为原始的二进制数据。我们需要该数据以一个文件的形式提供,以便元素树分析器可以对其进行操纵,因此使用bytes.decode() 方法将二进制数据转换为使用UTF-8编码的字符串(这也是XML文件所使用的),我们创建了一个类似于文件的io.StringlO对象,并将包含整个XML文件的字符串作为其数据。

tree = xml.etree.E!ementTree.ElementTree()

root = tree.parse(fh)

stations =[]

for element in tree.getiterator(“station_name”):

stations.append(element.text)

这里,我们创建一个新的
xml.etree.ElementTree.ElementTree对象,并赋予一个文件对象,文件对象提供了我们需要分析的XML。在使用元素树分析器时,已经有一个以读模式打开的文件传递给分析器,尽管实际上分析器要读取的是io.StringlO对象中的字符串。我们需要提取出所有气象站的名称,这可以使用xml.etree.ElementTree. ElementTree.getiterator()方法实现,该方法返回一个迭代子,该迭代子可以返回具有给定标签名的所有
xml.etree.ElementTree.Element对象。我们只需要使用元素的text属性来取回文本。像os.walk()一样,我们不需要自己进行任何递归操作,迭代子方法将自动做到。我们也不需要指定标签——迭代子将返回整个XML文档中的每个元素。

其他模块

我们没有足够的空间来展示标准库中提供的近200个包与模块。尽管如此,上面给出的常用模块概览也足以让读者领略标准库的强劲功能,以及某些关键包的应用领域。在本节的最后一个小节中,我们只是讨论其他一些读者可能感兴趣的模块。

在前一节中,我们看到了使用doctest模块,可以超级容易地在docstrings中创建 tests并运行之。标准库还提供了一个单元测试框架,由unittest模块实现一这实际上是Java JUnit测试框架的Python版。doctest模块还提供了一些与unittest模块的基本整合。此外,还有一些第三方测试框架,列如,codespeak.net/py/dist/处的py.test以及
www.somethingaboutorange.com/mrl/projects/nose/处的 nose。

非交互式的应用程序,列如服务器,一般会通过写入日志文件来报告问题dogging 模块提供了一个用于日志相关操作的统一接口,除了可以写入日志文件外,该模块还可以通过HTTP GET或POST请求写入日志,或使用email、sockets。

标准库提供了许多模块,用于内省与代码操纵,尽管大部分超出本书的范围,但 有一个pprint值得关注,其中提供了一些函数,用于“优美打印” Python对象,包括组合数据类型,这些功能有些时候对调试是有用的。

threading模块提供了对创建线程化应用程序的支持,queue模块提供了三种不同类型的thread-safe队列。

Python没有提供对GUI程序设计的本原支持,但有几个GUI库可供Python程序使用,列如使用tkinter模块的Tk库,一般是作为标准进行安装的。

abc (抽象基类)模块提供了用于创建抽象基类的必要函数。 copy模块提供了 copy.copy()函数与copy.deepcopy()函数。 对外部函数的访问,也就是说,对共享库(Windows中的.dll文件,Mac OS X中 的.dylib文件,Linux中的.so文件)中函数的访问,可以使用ctypes模块实现。Python 还提供了一个C API,因此,使用C语言创建自定义数据类型与函数,并使其为Python 所用是可能的.ctypes模块与Python的C API都超出了本书的范围。

如果这里提及的包与模块都不能提供所需要的功能,在从头开始编写程序之前, 对Python文档的Global Module Index进行检査是有价值的,可以了解是否有适当的可用模块,由于这里我们不可能面面俱到。如果找不到,还可以尝试Python Package Index (pypi.python.org/pypi),其中也包含几千个Python附件,从较小的单文件实现所有功能的模块,到很大的库与框架包(包含源代码与数百个模块),都在其中展示。

以上内容部分摘自视频课程05后端编程Python-12标准库概览,更多实操示例请参照视频讲解。跟着张员外讲编程,学习更轻松,不花钱还能学习真本领。

© 版权声明

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
none
暂无评论...