Post

《Effective Python》笔记-第10章 协作开发

第八十二条:学会寻找由其他Python开发者所构建的模块

如果面对一项自己不熟悉的需求,可以去PyPI(Python Package Index, 网址为https://pypi.org)搜索一下,看看有没有哪个软件包能够帮你更快达到目标。

可以用pip命令行工具从PyPI里面安装软件包,大多数PyPI模块都是自由及开源软件。pip最好与内置的venv模块搭配使用,这样可以给不同的项目安装不同版本的软件包,以适应每个项目自身的要求。

第八十三条:用虚拟环境隔离项目,并重建依赖关系

因为同一个模块在Python的全局环境中只能存在一个版本。如果某个软件包需要使用新版模块,另一个软件包需要使用旧版模块,那么会遇到两难局面:无论这个模块是否升级,这两个软件包都会有一个无法运行。这种情况通常称为dependency hell。

我们可以在每个虚拟幻境里,分别用pip命令安装它所需要的软件包,这样的话,同一台电脑中就可以存在许多互不冲突的环境了。

python -m venv命令可以创建虚拟环境,source bin/activate与deactivate命令分别可以启用与禁用该环境。

python -m pip freeze > requirements.txt命令可以把当前环境所依赖的软件包保存到文件中,之后可以通过python -m pip install -r requirements.txt在另一套环境重新安装这些包。

venv好像已经过时了,现在大部分开发项目都在使用miniconda

第八十四条:每一个函数、类与模块都要写docstring

每个模块、类、方法与函数都应该编写docstring文档,并且要实现代码保持同步。

模块的docstring要介绍本模块的内容,还要指出用户必须了解的关键类与重要函数。

类的docstring要写在class语句的正下方,描述本类的行为与重要的属性,还要指出子类应该如何正确地继承这个类。

函数与方法的docstring要写在def语句地正下方,描述本函数的每个参数、函数的返回值,可能抛出的异常以及其他相关的行为。

如果某些信息已经通过类型注解表达过了,那就不要在docstring中重复了。

第八十五条:用包来安排模块,以提供稳定的API

Python的包是一种包含其他模块的模块。这种结构让我们可以把代码划分成多个互不冲突的名称空间,即便两个实体同名,也能用他们所属的模块加以区分。

如果要构建的包比较简单,那就把其中每个模块所对应的源文件都直接放在本包的目录下,并给目录里面创建一份__init__.py文件。这样的话,这些源文件所表示的模块就会变成本包的子模块。这个目录里还可以创建子目录,以构建其他包。

第八十六条:考虑用模块级别的代码配置不同的部署环境

程序通常需要部署到许多种环境里,无论在哪一种环境中运行程序,都必须先准备好相关的资源,并做出适当的配置。

可以像编写普通的Python语句那样,直接在模块作用域书写配置逻辑,以定制该模块的内容,从而针对不同的环境作出适当的部署。

还可以根据其他一些外部因素来调整模块的内容,例如通过sys或os模块查询语操作系统有关的信息,并据此定制该模块。

第八十七条:为自编的模块定义根异常,让调用者能够专门处理与此API有关的异常

给模块定义异常,可以让使用这个模块的API用户将他们自己的代码与这个模块所提供的API隔开,以便分别处理其中的错误。

API用户在处理完API所属模块有可能抛出的具体异常后,可以写一个针对模块跟异常的except块,如果程序进入这个快,那就说明他使用API的方式可能有问题,例如可能忘记处理某种本来应该处理的具体异常。

API用户还可以再写一个except块以捕获整个Python体系之中的跟异常,如果成如需进入到了那个快,那说明所调用的APi可能实现地有问题。

在模块地跟异常下,可以设立几个门类,让具体的异常不要直接继承总的跟异常,而是继承各自门类地那个分跟异常,这样的话,使用这个模块地开发者,就可以只关注这几个门类,即便你修改了某个门类之下的具体异常,也不会影响到他们已经写好的那些代码。

第八十八条:用适当的方式打破循环依赖关系

如果两个模块都要在开头引入对方,那就会形成循环依赖关系,这有可能导致程序在启动时崩溃。

要想打破依赖循环,最好的办法是把这个两个模块都要用到地那些代码重构到整个依赖体系的最底层。

如果不想大幅重构代码,也不想代码变得太复杂,那么最简单的方案是通过动态引入来消除循环依赖关系。

第八十九条:重构时考虑通过warnings提醒开发者API已经发生变化

设计新版API的时候,可以通过warnings模块把已经过时时地用法通知到调用者,让他们看到消息尽快改用新的写法,以防程序在我们彻底放弃旧版API之后崩溃。

在命令行界面执行Python解释器的时候,可以开启-W error选项,从而将警告视为错误。这在执行自动化测试的过程中特别有用,因为这样可以及时发现受测程序所依赖的API是否已经推出了新的版本。

如果成需要部署到生产环境,那么可以通过logging模块将警告信息重新定向到日志系统,把程序在运行过程中遇到的警告纳入现有的错误报告机制中。

如果你设计的APi会发出警告,那么应该为此编写测试,确保下游开发者在使用API地过程中,能够在适当的时机收到正确的警告信息。

第九十条:考虑通过typing做静态分析,以消除bug

Python提供了内置的typing模块与一套特殊的写法,可以给变量、字段、函数与方法标注类型信息。

静态类型检查工具可以利用标注的类型信息检查出许多常见的bug,而不用让它们到程序运行地时候再暴露。

有一些建议可以指导我们,程序里面哪些地方应该加类型注解,如何在设计API的时候用类型注解,以及怎样才能让注解工作不影响编程效率。

This post is licensed under CC BY 4.0 by the author.