Alan Hou的个人博客

Odoo 17开发者指南第七章 调试模块

第 5 章 基础服务端开发中,我们学习了如何编写模型方法来实现模块的逻辑。然而,当我们遇到错误或逻辑问题时,可能会陷入困境。为了解决这些错误,我们需要进行详细的检查,这可能需要时间。幸运的是,Odoo 为您提供了一些调试工具,可以帮助您找到各种问题的根本原因。在本章中,我们将详细了解各种调试工具和技术。

在本章中,我们将涵盖以下内容:

自动重载和 --dev 选项

在前面的章节中,我们看到了如何添加模型、字段和视图。每当我们对 Python 文件进行更改时,都需要重启服务器才能应用这些更改。如果我们在 XML 文件中进行更改,则需要重启服务器并更新模块才能在用户界面中反映这些更改。如果您正在开发一个大型应用程序,这可能会非常耗时且令人沮丧。Odoo 提供了一个命令行选项 --dev 来克服这些问题。--dev 选项有几种可能的值,在本节中我们将查看其中的每一个。

准备工作

在您的开发环境中,使用以下 shell 命令安装 inotifywatchdog。如果没有 inotifywatchdog,自动重载功能将无法工作:

如何实现…

要启用 dev 选项,您需要从命令行使用 --dev=value。此选项的可能值包括 allreloadpudb|wdb|ipdb|pdbqwebwerkzeugxml。请查看以下内容以获取更多信息。

工作原理…

查看以下列表,了解所有 --dev 选项及其用途:

如果您只想启用少数选项,可以使用逗号分隔的值,如下所示:

重要提示

如果您对数据库结构进行了更改,例如添加了新字段,--dev=reload 选项将不会在数据库模式中反映这些更改。您需要手动更新模块;它仅适用于 Python 业务逻辑。如果您添加了新视图或菜单,--dev=xml 选项将不会在用户界面中反映这些更改。您需要手动更新模块。当您设计视图或网站页面的结构时,这非常有用。如果用户从 GUI 更改了视图,则 --dev=xml 将不会从文件中加载 XML。Odoo 将使用用户更改的视图结构。


生成服务器日志以帮助调试方法

服务器日志对于查明崩溃前运行时发生了什么非常有用。在调试出现问题时,也可以添加日志以提供额外信息。本节向您展示如何向现有方法添加日志记录。

准备工作

我们将向以下方法添加一些日志记录语句,该方法将产品库存水平保存到文件中(您还需要向 manifest 添加 productstock 模块的依赖项):

如何实现…

为了在执行此方法时获取一些日志,请执行以下步骤:

  1. 在代码开头导入 logging 模块:

  2. 在模型类定义之前,获取模块的日志记录器:

  3. 修改 export_stock_level() 方法的代码,如下所示:

工作原理…

步骤 1Python 标准库导入 logging 模块。Odoo 使用此模块来管理其日志。

步骤 2 为 Python 模块设置日志记录器。我们在 Odoo 中使用惯用语 __name__ 作为日志记录器名称的自动变量,并将其命名为 _logger

重要提示

__name__ 变量由 Python 解释器在模块导入时自动设置,其值是模块的完整名称。由于 Odoo 对导入做了一些处理,附加模块被 Python 视为属于 odoo.addons Python 包。因此,如果代码位于 my_hostel/models/hostel.py 中,__name__ 将是 odoo.addons.my_hostel.models.hostel

这样做,我们获得了两个好处:

步骤 3 使用日志记录器生成日志消息。可用的方法(按日志级别递增)有 debuginfowarningerrorcritical。所有这些方法都接受一条消息,您可以在其中使用 % 替换以及要插入到消息中的附加参数。您无需自己处理 % 替换;如果必须生成日志,logging 模块会足够智能地执行此操作。如果您以 INFO 日志级别运行,那么 DEBUG 日志将避免替换,从长远来看,这会消耗 CPU 资源。

本节中展示的另一个有用方法是 _logger.exception(),它可以在异常处理程序中使用。该消息将以 ERROR 级别记录,并且堆栈跟踪也会打印在应用程序日志中。

更多内容…

您可以从命令行或从配置文件中控制应用程序的日志记录级别。有两种主要方法可以做到这一点:

第一种方法是使用 --log-handler 选项。它的基本语法如下:--log-handler=prefix:level。在这种情况下,prefix 是日志记录器名称路径的一部分,levelDEBUGINFOWARNINGERRORCRITICAL。如果您省略前缀,则设置所有日志记录器的默认级别。例如,要将 my_hostel 日志记录器的日志记录级别设置为 DEBUG 并保持其他附加组件的默认日志级别,您可以按如下方式启动 Odoo:

可以在命令行上多次指定 --log-handler。您也可以在 Odoo 实例的配置文件中配置日志处理程序。在这种情况下,您可以使用逗号分隔的 prefix:level 对列表。例如,以下行与之前的最小日志输出配置相同。我们默认保留最重要的消息和错误消息,但 werkzeug 生成的消息除外,我们只需要关键消息,以及 odoo.service.server,我们保留信息级别消息,包括服务器启动通知:

有一些设置日志级别的快捷方式。以下是其中的列表:

使用 Odoo shell 交互式地调用方法

Odoo Web 界面主要面向最终用户,尽管开发者模式解锁了许多强大的功能。然而,通过 Web 界面进行测试和调试并不是最简单的方法,因为您需要手动准备数据、在菜单中导航以执行操作等等。Odoo shell 是一个命令行界面,您可以使用它来发出调用。本节向您展示如何启动 Odoo shell 并执行操作,例如在 shell 中调用方法。

准备工作

我们将重用上一节中用于生成服务器日志以帮助调试方法的相同代码。这允许 product.product 模型添加一个新方法。我们假设您有一个已安装并可用的附加组件实例。在本节中,我们期望您有一个名为 project.conf 的 Odoo 配置文件用于此实例。

如何实现…

为了从 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 实例,并初始化一些在输出中提到的全局变量:

步骤 34 使用 env 获取一个空记录集并根据 XML ID 查找记录。步骤 5product.product 记录集上调用方法。这些操作与您在方法内部使用的操作相同,细微差别在于我们使用 env 而不是 self.env(尽管两者都可以,因为它们是相同的)。请参阅**第 5 章《基础服务端开发》**以获取有关可用内容的更多信息。

步骤 6 提交数据库事务。在这里这不是严格必要的,因为我们没有修改数据库中的任何记录,但是如果我们这样做了并希望这些更改持久化,这是必要的;当您通过 Web 界面使用 Odoo 时,每个 RPC 调用都在其自己的数据库事务中运行,Odoo 会为您管理这些事务。在 shell 模式下运行时,情况不再如此,您必须自己调用 env.cr.commit()env.cr.rollback()。否则,当您退出 shell 时,任何正在进行的事务都会自动回滚。测试时,这没问题,但如果您使用 shell(例如,编写实例配置脚本),请不要忘记提交您的工作!

更多内容…

在 shell 模式下,默认情况下,Odoo 打开 Python 的 REPL shell 界面。您可以使用 --shell-interface 选项使用您选择的 REPL。支持的 REPL 是 ipythonptpythonbpythonpython

使用 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 命令三次,以遍历方法的前几行。您也可以使用快捷方式 n

  6. 使用 p 命令显示 productsfname 变量的值:

  7. 更改 fname 的值以指向 /tmp 目录:

  8. 使用 return 命令(快捷方式:r)执行当前函数:

  9. 使用 cont 命令(快捷方式:c)恢复程序执行:

工作原理…

步骤 1 中,我们通过调用 Python 标准库中 pdb 模块的 set_trace() 方法,在方法的源代码中硬编码了一个断点。当执行此方法时,程序的正常流程停止,您会获得一个 (Pdb) 提示符,您可以在其中输入 pdb 命令。

步骤 2 使用 shell 模式调用 stock_level_export() 方法。也可以正常重启服务器并使用 Web 界面生成对您需要跟踪的方法的调用,方法是单击用户界面上的相应元素。

当您需要使用 Python 调试器手动单步执行某些代码时,这里有一些技巧可以让您的生活更轻松:

步骤 38 使用几个 pdb 命令来单步执行方法的执行。以下是 pdb 的主要命令摘要。其中大多数也可以使用首字母作为快捷方式。我们在以下列表中用括号中的可选字母表示:

更多内容…

在本节中,我们插入了 pdb.set_trace() 语句以中断到 pdb 进行调试。我们也可以使用 pdb.runcall() 直接从 Odoo shell 中启动 pdb,当您无法轻松修改项目的代码时,这非常有用。此函数将方法作为第一个参数,将要传递给函数的参数作为下一个参数。因此,在 Odoo shell 中,您执行以下操作:

在本节中,我们重点介绍了 Python 标准库中的 Python 调试器 pdb。了解此工具非常有用,因为它保证在任何 Python 发行版上都可用。还有其他可用的 Python 调试器,例如 ipdb (https://pypi.python.org/pypi/ipdb) 和 pudb (https://pypi.python.org/pypi/pudb),它们可以用作 pdb 的直接替代品。它们共享相同的 API,并且您在本节中看到的大多数命令都保持不变。当然,如果您使用 Python IDE 进行 Odoo 开发,您将可以访问与其集成的调试器。

另请参阅

如果您想了解有关 pdb 调试器的更多信息,请参阅 pdb 的完整文档:https://docs.python.org/3.9/library/pdb.html

理解调试模式选项

第 1 章 安装 Odoo 开发环境中,我们看到了如何在 Odoo 中启用调试/开发者选项。这些选项在调试和揭示一些进一步的技术信息方面非常有帮助。在本节中,我们将详细了解这些选项。

如何实现…

查看第 1 章 安装 Odoo 开发环境中的激活 Odoo 开发者工具一节,并激活开发者模式。激活开发者模式后,您将在顶部栏中看到一个带有错误图标的下拉菜单,如下图所示:

图7.1:开启调试模式之后的选项

在此菜单中,您将看到各种选项。尝试使用它们以查看它们的实际效果。下一节将更详细地解释这些选项。

工作原理…

让我们通过以下几点了解有关这些选项的更多信息:

重要提示

您可以从 Edit View 选项修改视图定义。此更新的定义将适用于当前数据库,当您更新模块时,这些更改将被删除。因此,最好从模块中修改视图

我们已经了解了调试菜单下的所有可用选项。这些选项可以用于多种方式,例如调试、测试和修复问题。它们也可以用于探索视图的源代码。

退出移动版