11 进阶:标准库 =============== Python 标准库(Python Standrad Library)中包含了大量有用的模块,同时也是每个标准的 Python 安装包中的一部分。熟悉 Python 标准库十分重要,因为只要你熟知这些库可以做到什么事,许多问题都能够轻易解决。 我们将探索这个库中的一些常用模块。你能在你的 Python 安装包中附带的文档中的\ `“库概览(Library Reference)” 部分 `__\ 中查找到所有模块的全部细节。 让我们来了解一些有用的模块。 **注意:**\ 如果你觉得本章内容过于超前,你可以先跳过本章。不过,我强烈建议你在适应了采用 Python 进行编程后再来看看本章。 系统内置模块 ------------ - **os** : 对操作系统服务提供了可移植的( portable)的接口。 - **sys** : 包括跟python解析器和环境相关的变量和函数。 - **decimal** : python中的float使用双精度的二进制浮点编码来表示的,这种编码导致了小数不能被精确的表示,例如0.1实际上内存中为0.100000000000000001,还有3*0.1 == 0.3 为False.decimal就是为了解决类似的问题的,拥有更高的精确度,能表示更大范围的数字,更精确地四舍五入。 - **math** : 定义了标准的数学方法,例如cos(x),sin(x)等。 - **random** : 随机数生成。 - **io** : 实现了各种IO形式和内置的open()函数。 - **datetime** : 时间日期相关函数。 - **timeit** : 计时函数,调试相关。 - **logging** : 将一些调试(Debugging)信息或一些重要的信息储存在某个地方。 下面我们来详细介绍几个标准库。 ``OS`` 模块 ----------- - **os.name()**: 获取当前体系平台, Windows下返回"“nt”,Linux下返回”“posix”"。 - **os.linesep()**: 获取当前平台应用的行终止符。 Windows下返回"“/r/n”, Linux应用”“/n”。 - **os.getcwd()**: 获取当前工作目录,即当前python脚本工作的目录路径。 - **os.listdir(path)**:返回指定目录下的所有文件和目录名。 - **os.path.split()**:分离路径中的目录名和文件名。 - **os.path.exists()**:检查路径是否存在。 - **os.path.isfile()**: 判断是否为文件。 可以通过下面的例子来测试os模块的有关函数: .. code:: python >>> import os >>> print(os.getcwd()) >>> print(os.listdir("D:\\")) >>> print(os.path.exists("D:\\test")) .. _sys: ``sys`` 模块 ------------ ``sys`` 模块包括了一些针对特定系统的功能。我们已经了解过 ``sys.argv`` 列表中包括了命令行参数。 想象一些我们需要检查正在使用的 Python 软件的版本,\ ``sys`` 模块会给我们相关的信息。 .. code:: python >>> import sys >>> sys.version_info sys.version_info(major=3, minor=5, micro=1, releaselevel='final', serial=0) >>> sys.version_info.major == 3 True **它是如何工作的** ``sys`` 模块包含一个 ``version_info`` 元组,它提供给我们版本信息。第一个条目是主版本信息。我们可以调出这些信息并使用它。 除此之外,\ ``sys`` 模块还有以下功能: - **sys.argv** 获取命令行传入参数。 – sys.argv[0] 为脚本名, sys.argv[1] 为第一个参数 - **sys.getdefaultencoding()**: 获取当前终端编码,一般默认为ascii。 - **sys.getfilesystemencoding()**: 获取文件系统编码, Windows下返回"“mbcs”“, mac下返回”“utf-8”"。 - **sys.path**: 命令搜索路径。 ``decimal`` 模块 ---------------- Python中浮点数默认提供16位精度,无法精确存储十进制数。十进制数学计算模块decimal可以精确处理十进制。 .. code:: python >>> a="%.20f" %(1/3.) >>> a="%.20f" %(2.645) >>> a="%.20f" %(2.675) >>> round(2.675,2) >>> print(0.1+0.1+0.1-0.3) 5.55111512313e-17 >>> from decimal import Decimal as D >>> D('0.1') + D('0.1') + D('0.1') - D('0.3') Decimal("0.0") ``decimal`` 精度控制 ~~~~~~~~~~~~~~~~~~~~ .. code:: python >>> from decimal import Decimal as D >>> from decimal import getcontext >>> getcontext().prec 28 >>> D(1)/D(7) Decimal('0.1428571428571428571428571429') >>> getcontext().prec=6 >>> D(1)/D(7) Decimal('0.142857') >>> D(str(1.12)/D(7)) ``math`` 数学模块 ----------------- Python内置的常规数学计算模块,满足一般的计算需求。复数运算可使用 cmath 模块。 .. code:: python >>> import math >>> math.pi >>> math.e >>> math.sin(2*math.pi/180) >>> math.fmod(9.8,4.0) - **hypot(x,y)** 从原点(0,0)到(x,y)的直线距离。 - **radians(x)** 角度数转弧度。 ``random`` 模块 --------------- 此模块专门用于生成随机数。 .. code:: python >>> import random >>> random.randint(0,99) #随机整数 >>> random.randrange(0, 101, 2) #随机偶数 >>> random.random() #随机浮点数 >>> random.uniform(1, 10) #均匀分布 >>> random.choice('?abc&%^*f') #随机字符 >>> random.sample('abcdefghij',3) >>> items = [1, 2, 3, 4, 5, 6] >>> random.shuffle(items) #洗牌 ``datetime`` 模块 ----------------- 此模块专门用于处理日期和时间。date:表示日期的类; time:表示时间的类;datetime:表示日期时间; timedelta:表示时间间隔, tzinfo:与时区有关的相关信息。 .. code:: python >>> import datetime as dt >>> print('date.max:', dt.date.max) >>> print('date.min:', dt.date.min) >>> print('date.today():', dt.date.today()) >>> dt.date.isoweekday(dt.date.today()) >>> dt.date.today()+dt.timedelta(7) >>> print('Time:', dt.time(12,5,4)) >>> dt.datetime.now() 时间与字符串 ~~~~~~~~~~~~ .. code:: python >>> from datetime import datetime as dtdt >>> dtdt.now() >>> dtdt.strftime(dtdt.now(),'%c') >>> d = dtdt.now() - dtdt.strptime('2015/12/2020:56:30','%Y/%m/%d %H:%M:%S') >>> (d.days, d.seconds, d.microseconds) - **%a** 星期的简写, %A 星期的全称 - **%b** 月份的简写, %B 月份的全称 - **%I** 小时( 12小时制), %W 周数(星期一起算) ``timeit`` 模块 --------------- 此模块专门用于计时。 .. code:: python >>> import timeit as ti >>> t = ti.Timer('x=range(100)') >>> t.timeit() >>> t.timeit(100) >>> ti.timeit('x=range(100)',number=100) >>> t.repeat(3, 20000) .. _logging: 日志模块 -------- 如果你想将一些调试(Debugging)信息或一些重要的信息储存在某个地方,以便你可以检查你的程序是否如你所期望那般运行,应该怎么做?你应该如何将这些信息“储存在某个地方”?这可以通过 ``logging`` 模块来实现。 保存为 ``stdlib_logging.py``\ : .. code:: python import os import platform import logging if platform.platform().startswith('Windows'): logging_file = os.path.join(os.getenv('HOMEDRIVE'), os.getenv('HOMEPATH'), 'test.log') else: logging_file = os.path.join(os.getenv('HOME'), 'test.log') print("Logging to", logging_file) logging.basicConfig( level=logging.DEBUG, format='%(asctime)s : %(levelname)s : %(message)s', filename=logging_file, filemode='w', ) logging.debug("Start of the program") logging.info("Doing something") logging.warning("Dying now") 输出: .. code:: console $ python stdlib_logging.py Logging to /Users/swa/test.log $ cat /Users/swa/test.log 2014-03-29 09:27:36,660 : DEBUG : Start of the program 2014-03-29 09:27:36,660 : INFO : Doing something 2014-03-29 09:27:36,660 : WARNING : Dying now 如果你不能运行 ``cat`` 命令,你可以通过一款文本编辑器打开 ``test.log`` 文件。 **它是如何工作的** 我们使用了三款标准库中的模块——\ ``os`` 模块用以和操作系统交互,\ ``platform`` 模块用以获取平台——操作系统——的信息,\ ``logging`` 模块用来 *记录(Log)* 信息。 首先,我们通过检查 ``platform.platform()`` 返回的字符串来确认我们正在使用的操作系统(有关更多信息,请参阅\ ``import platform; help(platform)``\ )。如果它是 Windows,我们将找出其主驱动器(Home Drive),主文件夹(Home Folder)以及我们希望存储信息的文件名。将这三个部分汇聚到一起,我们得到了有关文件的全部位置信息。对于其它平台而言,我们需要知道的只是用户的主文件夹位置,这样我们就可获得文件的全部位置信息。 我们使用 ``os.path.join()`` 函数来将这三部分位置信息聚合到一起。使用这一特殊函数,而非仅仅将这几段字符串拼凑在一起的原因是这个函数会确保完整的位置路径符合当前操作系统的预期格式。 然后我们配置 ``logging`` 模块,让它以特定的格式将所有信息写入我们指定的文件。 最后,无论这些信息是用以调试,提醒,警告甚至是其它关键的消息,我们都可以将其聚合并记录。一旦程序开始运行,我们可以检查这一文件,从而我们便能知道程序运行过程中究竟发生了什么,哪怕在用户运行时什么信息都没有显示。 .. _motw: 每周模块系列 ------------ 标准库中还有许多模块值得探索,例如一些\ `用以调试(Debugging)的模块 `__\ , `处理命令行选项的模块 `__\ ,\ `正则表达式(Regular Expressions)模块 `__ 等等等等。 进一步探索标准库的最好方法是阅读由 Doug Hellmann 撰写的优秀的 `Python Module of the Week `__ 系列(你还可以阅读\ `它的实体书 `__\ 或是阅读 `Python 官方文档 `__\ )。 总结 ---- 在这一章我们探索了 Python 标准库中提供的诸多的模块的一些功能。我强烈建议你浏览 `Python 标准库文档 `__\ 来了解所有可以使用的模块。