本博客包含多个文档和书籍的翻译,但有能力者推荐阅读英文原版

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

Odoo Alan 6个月前 (05-19) 1121次浏览 0个评论

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

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

  • 自动加载和–dev 选项
  • 产生服务日志来帮助调试方法
  • 使用Odoo shell来交互调用方法
  • 使用Python调试器来追踪方法执行
  • 使用Odoo社区联盟维护者质量工具
  • 理解调试模式选项

引言

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

自动加载和–dev 选项

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

准备工作

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

如何操作…

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

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

运行原理…

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

  • reload:无论何时对Python做出修改,我们需要重启该服务来在Odoo中应用这些修改。–dev=reload选项会在Python做出修改时自动重载Odoo服务。如未安装Python的watchdog包则无法使用这一功能。
  • qweb:我们可以在Odoo中使用QWeb模板来创建动态网页。在第十五章 CMS网站开发中我们将了解如何使用QWeb模型开发网页。可以通过t-debug 属性在QWeb模板中调试问题。t-debug选项仅在你通过 –dev=qweb启用dev模式时才会生效。
  • werkzeug:Odoo 使用werkzeug来处理HTTP请求。Odoo内部会捕获所有由werkzeug生成的异常。如果你使用–dev=werkzeug,werkzeug的交互式调试器会在生成异常时在网页上展示。
  • xml:每当你在视图结构中做出更改时,都需要重载服务并更新模型来应用这些更改。通过 –dev=xml选项,仅需在浏览器中重载Odoo,无需再重启服务或更新模块。
  • pudb|wdb|ipdb|pdb:我们可以通过Python调试器(PDB)来获取错误的更多详情。在你使用–dev=pdb选项时,它会在Odoo中产生异常时激活PDB。Odoo支持4种Python调试器:pudb, wdb, ipdb和pdb。
  • all:如果使用–dev=all,会启用上述的所有选项。

ℹ️如果你对数据库结构做出修改,比如添加了新字段, –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。

这么做有两个好处:

  • odoo日志记录器的全局配置会应用于我们日志记录器中,这是因为logging模块中日志记录器层级结构。
  • 日志会以完整的模块路径为前缀,这对查找所生产日志的给定行会有很大帮助。

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

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

扩展知识…

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

  • 可以使用–log-level命令行选项来全局控制日志级别。参见第一章 安装Odoo开发环境获取更多详情。
  • 可以使用–log-handler=prefix:level来设置给定日志记录器的日志级别。在这种情况下,前缀为日志记录器名称的一段路径,级别为DEBUG, INFO, WARNING, ERROR或CRITICAL。如果你省去了前缀,则为所有记录器设置默认级别。例如,设置my_library日志记录器的日志级别为DEBUG并让其它插件保持默认日志级别,可以通过如下命令启动Odoo:

可在命令行中多次指定–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实例并初始化了一些全局变量,参见如下的输出:

  • env是连接了数据库及在命令行或配置文件中指定的环境。
  • odoo是导入的odoo包。可以在该包内访问所有的Python模块并执行你想要的操作。
  • openerp是为保持向后兼容保留的odoo包别名。
  • self是包含Odoo超级用户(Administrator)单条记录的res.users的一个记录集,它与env环境关联。

第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调试器单步进入代码时,以下几个贴士会让你更为轻松:

  • 降低日志级别来避免过多日志行,这会污染调试器的输出。通常可以ERROR级别开始。可能在使用中会需要启用更丰富的指定日志记录器,可通过使用–log-handler命令行选项来实现(参见产生服务日志来帮助调试方法一节)。
  • 使用–workers=0运行服务来避免可能导致在不同进程中两次到达相同断点的多进程问题。
  • 通过–max-cron-threads=0运行服务来关闭ir.cron任务的处理,不关闭它可能会在单步调试方法时触发,进行产生不必要的日志和负面效果。

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

  • h(elp):它会显示pdb命令的帮助信息。
  • a(rgs):它显示当前函数/方法的参数值。
  • l(ist):它显示11行代码块的源码执行,初始中间位置为当前行。后续调用会在源码文件中不断深入。你还可传递两个整型的start和end,指定显示的区域。
  • p:它打印变量。
  • pp:它格式化打印变量(对于列表和字典非常有用)。
  • w(here):它会显示调用栈,当前行在最底部,而Python解释器在顶部。
  • u(p):它在调用栈中上移一级。
  • d(own)::它在调用栈中下移一级。
  • n(ext):它执行代码的当前行,然后停止。
  • s(tep):它会进入方法调用执行的内部。
  • r(eturn):它恢复当前方法运行至执行返回语句。
  • c(ont(inue)):它恢复当前程序的执行至下一个断点。
  • b(reak) <args>:它创建一个新断点并展示其标识符,args可以为如下内容:
    • 留空:列出所有断点。
    • 行号:在当前文件的指定行中断。
    • 文件名:行号:在指定文件的指定行中断(在sys.path中搜索文件)。
    • 函数名:在指定函数的第一行中中断。
  • tbreak <args>:它类似于 break,但在到达断点时会取消断点,这样该行的连续执行不会再次触发断点。
  • disable bp_id:它会通过ID禁用某一断点。
  • enable bl_id:它会通过ID启用某禁用断点。
  • j(ump) lineno:执行的下一行为所指定行。可用于重新运行或跳过某些行。
  • (!) statement:它执行一个Python语句。如果命令不类似一个pdb命令的话可以省略 ! 字符。例如,在想要为变量名 a 设置值时需要使用它,因为a是args命令的简写形式。

扩展知识…

本节中,我们插入了一个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配置)。以下是关于该文件自定义区的说明:

  • addons:它与Odoo的插件模块毫无关系。用于要求Travis安装一些用于在测试环境里分发包的Ubuntu包。这节约了我们从源码安装Python包的时间,如 python-lxml,否则会花费大量时间。
  • env:这个版块定义环境变量和构建矩阵。维护者质量工具使用这些环境变量来了解要测试什么以及在独立的测试运行中运行每个env行:
    • VERSION:所测试的Odoo版本。
    • LINT_CHECK:在构建中使用0来取消flake8或Pylint测试,1则为启用。在矩阵中,我们设置第一个构建来执行lint测试,因为这很快速并我们想要快速的反馈来看代码是否符合标准或者linter是否发现了错误。
    • TESTS:对无需运行模块测试的构建使用0,否则使用1.
    • ODOO_REPO:在TESTS为1时这是用于测试的Odoo的GitHub仓库。在本节中,我们设置对官方https://github.com/odoo/odoo仓库及社区补丁仓库https://github.com/OCA/OCB同时设置了构建。如未设置,仅会使用官方仓库。
  • install:这一部分在构建环境中下载 maintainer-quality-tools并调用travis_install_nightly工具,用于在Travis中设置Odoo。
  • script:这一部分从maintainer-quality-tools中调用travis_run_tests。该脚本负责从构建矩阵中检查环境变量并执行相应的动作。
  • after_success:在script部分中的测试成功运行后,会运行travis_after_test_success脚本。在本节的上下文中,该脚本会使用https://coveralls.io查看模块的测试范围并在构建中生成报告。

扩展知识…

或许你对这个重度依赖于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

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

运行原理…

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

  • Run JS Tests:这个选项重定向到JavaScript QUnit测试用例,如下图所示。它会逐一开始运行所有测试用例。这里,你可以看到测试用例的进度和状态。在第十八章 自动化测试用例中,我们会学习如何创建我们自己的QUnit JavaScript测试用例:
    TODO
  • Run JS Mobile Tests:类似于前一个选项,它是用于对移动环境运行QUnit测试用例的。
  • Run Click Anywhere Tests:这一选项会开始对所有菜单进行逐一点击。它会检测所有视图和搜索过滤器。如果出现问题或存在回退,它会显示回溯。需要重载页面来停止这一测试。
  • Open View:这个选项会打开一个所有可用视图的列表。通过选择任一视图,可以无需定义任何菜单或动作即打开该视图。
  • Start Tour:Odoo使用导览来帮助新用户入手。它也使用导览来进行自动化测试。我们会在第十六章 网页客户端开发中创建一个上手导览。该选项会通过一个所有导览的列表打开一个对话框,如下图所示。通常点击导览右侧的播放按钮,Odoo会自动执行该导览的所有步骤:
    TODO
  • Edit Action:在第四章 创建Odoo插件模块添加菜单项和视图一节,我们添加了一个菜单项以及在Odoo中打开视图的动作。这些动作的详情以记录存储在数据库中。这一选项会打开我们打开展示当前视图的动作的记录详情。
  • View Fields:这个选项会在我们想要从用户界面中查看字段的详情时有所帮助。它会为当前模型显示一个字段列表。例如,如果你打开library.book模型的树状或表单视图,这个选项会显示library.book模型的字段列表。
  • Manage Filters:在Odoo中,用户可以从搜索视图中创建自定义过滤器。该选项会为当前模型打开一个自定义过滤器列表。这里,你可以修改自定义过滤器。
  • Technical Translations:这一选项会打开一个当前模型的翻译术语列表。你可以在这里修改模型的技术术语翻译。参见第十二章 国际化来学习翻译的更多知识。
  • Fields View Get:你可以继承并修改其它插件模块中的已有视图。在一些应用中,这些视图被多个插件模块继承。因此,很难清楚的了解整体视图的定义。通过这一选项,你可以获取应用所有继承后的最终视图定义。它在内部使用fields_view_get()方法。
  • Edit View: <view type>:这一选项会打开带有当前视图 ir.ui.view 记录的对话框。此选项是动态的,它会显示一个基于当前所打开视图的选项。这表示哪果你打开了看板视图,会获取到Edit View: Kanban option,而如果你打开表单视图,则会获取到Edit View: Form option。

    小贴士:我们可以通过Edit View选项修改视图定义。这一更新的定义会应用于当前数据库并在更新模块时删除这些修改。因此通过模型来修改视图会更好。

  • Edit Search View:这个选项和前面一个相同,但它会在当前模型的搜索视图中打开ir.ui.view记录。
  • Activate Assets Debugging:Odoo提供两种类型的开发者模式:开发者模式和带资源的开发者模式。通过这一选项,你可以将Developer mode切换为Developer mode with assets mode。查看第一章 安装Odoo开发环境中的激活Odoo开发者工具一节来获取更多详情。
  • Regenerate Assets Bundles:Odoo通过资源包来管理所有的CSS和JavaScript。这一选项删除老的JavaScript和CSS资源并生成新的。该选项对于因资源缓存产生的问题会很有帮助。我们将在第十五章 CMS网站开发中学习更多资源包相关知识。
  • Become Super User:这是版本12中的新选项。通过激活该选项,你可以切换为超级用户。此时即便没有访问权限也可访问这些记录。该选项不是所有用户都能用的,仅对拥有Administration: settings访问权限的用户可用。在激活这一模式之后,你会看到一个条状的顶部菜单,如下图所示:
    TODO
  • Leave Developer Tools:该选项允许我们退出开发者模式。
喜欢 (3)
[]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址