Alan Hou的个人博客

Odoo 12开发者指南第八章 调试

全书完整目录请见:Odoo 12开发者指南(Cookbook)第三版

本章中,我们将讲解如下小节:

引言

第六章 基本服务端部署中我们学习了如何编写模型方法来实现模块的逻辑。但是如果我们碰到复杂的问题时可能就不知所措了。Odoo为我们提供了一些调试工具来帮助我们查找各类问题的根由。本章中我们将详细的了解这一调试工具。

自动加载和–dev 选项

在前面的章节中,我们学习了如何添加模型、字段和视图。每当对Python文件进行修改时,我们需要重启服务来应用这些修改。如果我们对XML做出修改的话,需要重启服务并更新模块来在用户界面中反映这些修改。如果你在开发一个大型应用的话,这会非常耗时且令人沮丧。Odoo提供了一些命令行 –dev选项来处理这些问题。本节中,我们来学习如何使用这些选项。

准备工作

运行如下shell命令来在开发环境中安装watchdog。没有watchdog,就无法运行自动重载的功能:

如何操作…

要启用dev选项,我们需要在命令行中使用–dev=value。这一选项可以使用的值有all, reload, pudb|wdb|ipdb|pdb, qweb, werkzeug和xml。查看如下示例来获取更多信息:

如果你只想启用几个选项的话,可以使用逗号分隔的值,如下:

运行原理…

查看如下列表来了解所有–dev选项及其用途:

ℹ️如果你对数据库结构做出修改,比如添加了新字段, –dev=reload不会在数据库schema中进行反映。你需要手动更新模块,它仅用于Python的业务逻辑。

如果你添加了一个视图或菜单,–dev=xm也不会在用户界面中进行反映。需要手动更新模块。在设计视图结构或网页时这会很有帮助。

产生服务日志来帮助调试方法

服务日志对于了解崩溃前运行时发生了什么了会很有用。也可以添加日志来在调试问题时提供更多的信息。这一节展示如何向已有方法添加日志。

准备工作

我们会向如下方法添加一些日志语句,空会将产品的存储级别保存到一个文件中:

如何操作…

执行如下步骤在来执行方法时获取一些日志:

  1. 在代码的起始处,导入logging模块:
  2. 在定义模型类之前,为模块获取一个日志记录器:
  3. 修改export_stock_level()的代码如下:

运行原理…

第1步从Python标准库中导入了logging模块。Odoo使用这一模块来管理它的日志。

第2步为Python模块设置了一个日志记录器。我们使用了一个Odoo中常用的 __name__来作为一个日志记录器名称的自动变量,并称其为_logger。

ℹ️__name__变量由Python解释器在模块导入的时候自动设置,它的名称为模块的全名。因Odoo在导入时做了一些小动作,插件模块被Python视作属于odoo.addons Python包。因此,如果本节的代码放在 my_library/models/book.py中,__name__则为odoo.addons.my_library.models.book。

这么做有两个好处:

第3步中使用日志记录器来生成日志信息。可以使用的方法有(日志级别逐渐升高):debug, info, warning, error和critical。所有这些方法接收一条消息,在其中可以使用%替换符及其它插入到消息中的参数。你不应自己使用%替换符,在生成日志时logging足够智能的执行此操作。如果所运行的日志级别为INFO,那么DEBUG日志会避免替换减少长期的CPU开销。

本节中展示的另一个有用的方法是_logger.exception(),它可以在异常处理器中使用。消息会通过ERROR级别进行日志记录,栈的踪迹也会在应用日志中打印。

扩展知识…

你可以通过命令行或配置文件来控制应用的日志级别。这么做有两种主要方式:

可在命令行中多次指定–log-handler。也可以在Odoo实例的配置文件中配置日志处理器。那样,你可以使用前缀:日志级别的键值对组成的逗号分隔列表。例如,下面的这行配置和此前最小化日志输出的配置相同。默认我们保留最重要的消息及错误消息,除werkzeug产生的消息我们仅需要紧急消息,还有odoo.service.server我们保留包含服务启动消息等信息级别的消息。

使用Odoo shell来交互调用方法

Odoo网页界面供终端用户使用,虽然开发者模式解锁了许多强大的功能。但是,通过网页界面测试和调试不是种简单的方式,因为我们需要手动准备数据,导航至对应菜单来执行动作,等等。Odoo shell是一个命令行界面,可通过它来发布调用。本节展示如何启动Odoo shell以及在 shell 中执行调用方法等动作。

准备工作

我们将复用前一节中的代码在生成服务日志帮助调试方法。这让product.product模型可以新的方法。我们假定你的实例已安装并可使用该插件。本节中,我们预设你的Odoo实例有一个名为project.conf的配置文件。

如何操作…

需要执行如下步骤来通过Odoo shell调用export_stock_level()方法:

  1. 启动Odoo shell并指定项目配置文件:
  2. 查看错误消息并读取常规Python命令行输出之前显示的文本:
  3. 获取product.product记录集:
  4. 获取主仓储位置记录:
  5. 调用export_stock_level()方法:
  6. 在退出前执行事务:
  7. 通过按下Ctrl + D快捷键退出shell。

运行原理…

第1步使用odoo-bin shell脚本启动Odoo shell。所有常规的命令行参数在此处均可使用。我们使用-c来自指定项目配置文件以及–log-level来减少日志的输出量。在调试时,你可能会需要使用DEBUG日志级别来获取更具体的插件调试信息。

在向你提供Python命令行输出之前,odoo-bin shell脚本启动未监听网络的Odoo实例并初始化了一些全局变量,参见如下的输出:

第3和第4步使用env来获取一个空记录集并通过XML ID查找记录。第5步对product.product 记录集调用该方法。这些操作与你在方法中使用的相同,稍有不同的是我们使用env而非self.env (但两者均可使用,因为它们是一样的)。参见第六章 基本服务端部署获取更多相关知识。

第6步执行数据库事务。在这里并非必须,因为我们没有在数据库中修改任何记录,但如果你做了修改并希望这些修改持久化,就需要这么操作了;在通过网页界面使用Odoo时,每个RPC调用会运行它自己的数据库事务,由Odoo代为管理。在shell模式下运行时,则不再这样,你需要自己调用env.cr.commit()或env.cr.rollback()。否则在退出shell时,任何进行中的事务会自动被回滚。测试的情况下这不是问题,但如果你使用shell编写实例的配置脚本等时,记得要提交事务。

扩展知识…

默认在shell模式下,Odoo打开Python和REPL shell界面。我们可以通过–shell-interface选择来选择REPL。支持的REPL有ipython, ptpython, bpython和python:

译者注:REPL(Read Eval Print Loop)中文译作交互式解释器

使用Python调试器来追踪方法执行

有时,应用日志不足以判断何处出现了问题。所幸我们还有Python调试器。本节展示如何在方法中插件断点并手动追踪代码的执行。

准备工作

我们将复用本章中使用Odoo shell来交互调用方法一节的export_stock_level() 方法。确保你已准备好相关代码。

如何操作…

执行如下步骤来通过pdb追踪export_stock_level()的执行:

  1. 编辑该方法的代码,并插件高亮的那行代码:
  2. 运行该方法。我们会通过使用Odoo shell来交互调用方法一节中所讲解的Odoo shell:
  3. 在(Pdb)命令行,输入args命令(简写为 a)来获取传递给该方法的参数值:
  4. 输入list命令来查看代码运行所在行:
  5. 输入next命令3次来运行方法前几行代码。你可以使用简写形式n:
  6. 使用命令p来显示变量products和fname的值:
  7. 修改fname的值来指向/tmp目录:
  8. 使用命令return(简写形式:r)来执行当前函数:
  9. 使用命令cont(简写为c)来恢复程序的执行:

运行原理…

在第1步中,我们通过Python标准库中的pdb模块调用set_trace() 方法来在源代码中硬编码了一个断点。在该方法执行时,程序的正常流程停止,会进入到一个 (Pdb)命令行,在其中可输入pdb相关命令。

第2步使用shell模式调用了stock_level_export() 方法。也可以正常重启服务并使用网页界面点击相应的用户界面元素对所需追踪方法生成调用。

在需要手动使用Python调试器单步进入代码时,以下几个贴士会让你更为轻松:

第3到8步使用一些pdb命令来单步执行方法。以下是对pdb主要命令的一个总结。它们的大部分可使用第一个字母来作为简写。下面我们通过在括号中放入可选字母来进行表示:

扩展知识…

本节中,我们插入了一个pdb.set_trace()语句断点进入pdb来进行调试。我们还可以在Odoo shell中直接启动pdb,在无法轻易地使用pdb.runcall()修改项目代码是这会非常有用。这一函数接收一个方法做为参数,传递给函数的其它参数作为后续参数。因此,在 Odoo shell内,可以这么做:

本节中,我们集中学习Python标准库中的Python调试器。了解这一工具非常有用,因为它一定会在Python发行版中存在。还有其它的Python调试器供使用,如ipdbpudb,它们可作为pdb的替代。它们共享相同的API,本节中所学习的大部分命令都无需更改。当然,如果你使用Python IDE开发Odoo的话,还可以使用其内置的调试器。

其它内容

如果想要学习更多有关pdb调试器的知识,可参见pdb的完整文档:https://docs.python.org/3/library/pdb.html

使用Odoo社区联盟维护者质量工具

Odoo社区联盟(OCA)使用GitHub管理着大量的Odoo项目。联盟项目使用Travis CI来实现持续集成。本节将展示如何在你自己的GitHub仓库中使用社区开发的QA工具。

准备工作

学习本节,你需要拥有带有自己模块的一个公共的GitHub仓库。在编写本书时,OCA工具预设这个仓库中的子目录中包含多个插件。

如何操作…

要通过你的仓库集成OCA维护者质量工具,你需要执行如下步骤:

  1. 连接https://travis-ci.org/:
    TODO
  2. 选择Sign in with GitHub进行登录:
  3. 点击右上角你的名称来访问个人资料设置,如下图所示:
    TODO
  4. 点击Sync按钮来在Travis中载入你的公共仓库的信息。根据你仓库的多少可能会花费几分钟时间。
  5. 对于所有想要使用Travis的仓库,点击灰色的叉号切换为绿色的对号。
  6. 可以点击齿轮来访问各个仓库的各项设置,默认的设置也没有问题。
  7. 在你的仓库的本地克隆中,创建一个名为.travis.yml的文件并加入如下内容:
  8. 提交文件并将其推至GitHub:
  9. 进入travis-ci.org 页面并点击你的项目名称。应该会看到进行中的第一次构建。如果你的代码遵循OCA编码标准的话,可能第一次运行就显示绿色:
    TODO

运行原理…

在仓库中启用Travis CI时,Travis会在GitHub上注册一个钩子。默认,这个钩子会对仓库分支的每一次推送及每个拉取请求触发Travis CI构建。拉取请求基于临时合并构建来确保合并后的分支能通过测试。

这里所提供的Travis CI配置文件非常的高阶,很接近maintainer-quality-tools项目中sample_file子目录中的文件,可参见https://github.com/OCA/maintainer-quality-tools(我们删除了用于管理模块翻译的transifex配置)。以下是关于该文件自定义区的说明:

扩展知识…

或许你对这个重度依赖于Travis CI的完整设置并不感冒,而是想要使用一些更轻量级的工具来在日常工作中使用。好消息是本节中所展示的设置背后的一些工具是可以单独使用的,尤其是静态代码检查器Pylint和Flake8。

使用Pylint来检查代码

Pylint是针对Python的静态代码检查器。有一个非常有意思的项目名为pylint-odoo,它是特别针对Odoo进行检测的Pylint插件。要进行安装,运行如下命令,建议在虚拟环境中进行:

在完成安装后,可以通过如下命令来检测我们的插件模块:

这将会生成如下输出:

该模块的README文件(参见Github)会给出由这一工具执行的检测的最新列表。然后,你可以使用Pylint的命令行选项来调整输出。例如,如果你不想要进行特别针对 OCA的丢失的作者的检测,可以通过查看README中的消息ID(本例中为C8101)来删除这一检测并将其传递给-d或–disable命令行选项,如下:

可以将通过命令行传递给Pylint的选项存储在配置文件中来让日常维护工具更为轻松。

使用Flake8来检查代码

Flake8是另一个可用于检测代码格式是否正确的流行工具。支持开发的编程文本编辑器和IDE通常在输入时运行flake8的方式,高亮显示不符合flake8规则的代码块。

运行如下命令来安装flake8:

以下是针对 OCA 所使用的flake8配置文件:

在项目的根目录中将该文件命名为.flake8并保存,然后你应该就可以运行如下命令了:

更好的是在编辑器设置来对输入进行实时检查。

理解调试模式选项

第一章 安装Odoo开发环境中,我们学习了如何在Odoo中启用调试/开发者选项。这些选项对于调试或暴露更一些更进一步的技术信息会很有帮助。本章中我们来深入了解这些选项。

如何操作…

查看第一章 安装Odoo开发环境中的激活Odoo开发者工具一节,并激活开发者模式。在激活了开发者模式之后,可以顶部菜单栏的调试图标下拉菜单中看到如下选项:

TODO

在这个菜单中,你可以看到不同的选项。可以对每个选项进行点击查看。下一部分我们来详细说明这些选项。

运行原理…

让我们通过如下列表理深入的学习这些选项:

退出移动版