21

希望提高一个相当大的 Python 项目的质量。我对 PyLint 给我的警告类型很满意。但是,它们数量众多,难以在大型组织中实施。此外,我相信某些代码对于下一个 bug 可能出现的位置比其他代码更关键/敏感。例如,我想花更多的时间来验证一个被 100 个模块使用的库方法,而不是 2 年前最后一次接触并且可能不会在生产中使用的脚本。了解经常更新的模块也会很有趣。

是否有人熟悉 Python 工具或其他有助于此类分析的工具?

4

6 回答 6

15

您的问题类似于我在 SQA https://sqa.stackexchange.com/a/3082上回答的问题。这个问题与 Java 有关,这使得工具更容易一些,但我在下面有一些建议。

许多其他答案表明没有好的 Python 运行时工具。我在几个方面不同意这一点:

  1. 覆盖工具工作得很好
  2. 根据我在 Java 中使用工具的经验,Python 中的静态和动态分析工具比强类型较少动态语言中的弱,在此处为您提供良好的启发式方法已经足够好。除非你使用异常大量的动态特性(包括添加和删除方法、拦截方法和属性调用、玩导入、手动修改命名空间)——在这种情况下,你遇到的任何问题都可能与这种动态相关。 .
  3. Pylint 选择更简单的问题,并且不会检测动态类/实例修改和装饰器的问题 - 所以度量工具不测量这些并不重要
  4. 在任何情况下,您可以有效地集中注意力的地方不仅仅是依赖图。

选择代码的启发式

我发现在选择代码进行改进时有许多不同的考虑因素,它们既可以单独使用,也可以一起使用。请记住,首先,您需要做的就是找到一个富有成效的工作接缝——您不需要在开始之前找到绝对最差的代码。

用你的判断。

在通过代码库几个周期后,您将拥有大量信息,并且可以更好地继续您的工作——如果确实需要做更多工作的话。

也就是说,这是我的建议:

对业务的高价值:例如任何可能使您的公司花费很多钱的代码。其中许多可能是显而易见的或广为人知的(因为它们很重要),或者可以通过在启用了运行时分析器的系统上运行重要用例来检测它们。我使用覆盖率

静态代码指标:有很多指标,但我们关心的是:

请注意,这些工具是基于文件的。这可能是足够好的分辨率,因为您提到该项目本身有数百个模块(文件)。

频繁更改:频繁更改的代码是高度可疑的。该代码可能:

  • 历史上存在许多缺陷,经验上可能会继续这样做
  • 正在经历功能开发的变化(VCS 中的大量修订)

使用 VCS 可视化工具查找更改区域,例如本答案后面讨论的那些。

未覆盖的代码:测试未覆盖的代码。

如果您运行(或可以运行)您的单元测试、您的其他自动化测试和典型用户测试,请查看几乎没有覆盖的包和文件。没有覆盖有两个合乎逻辑的原因:

  • 该代码是必需的(并且很重要),但根本没有经过测试(至少是自动测试的)。这些领域风险极高
  • 该代码可能未使用并且是删除的候选者。

询问其他开发人员

您可能会对通过与服务时间较长的开发人员喝咖啡来收集的“气味”指标感到惊讶。我敢打赌,如果有人清理代码库中只有最勇敢的灵魂才会冒险的肮脏区域,他们会非常高兴。

可见性 - 检测随时间的变化

我假设您的环境有一个 DVCS(例如 Git 或 Mercurial)或至少一个 VCS(例如 SVN)。我希望您也在使用某种问题或错误跟踪器。如果是这样,则有大量可用信息。如果开发人员能够可靠地签入评论和问题编号,那就更好了。但是您如何将其可视化并使用它呢?

虽然您可以在单个桌面上解决问题,但设置一个持续集成 (CI) 环境可能是一个好主意,也许使用像Jenkins这样的工具。为了让答案简短,我将从现在开始假设詹金斯。Jenkins 附带了大量插件,这些插件对代码分析很有帮助。我用:

这让我可以看到随时间发生的变化,我可以从那里深入了解。例如,假设 PyLint 违规在模块中开始增加 - 我有增加的证据,并且我知道发生这种情况的包或文件,因此我可以找出谁参与其中并与他们交谈。

如果您需要历史数据并且您刚刚安装了 Jenkins,请查看是否可以运行一些从项目开始时开始的手动构建,并及时进行一系列跳跃直到现在。您可以从 VCS 中选择里程碑发布标签(或日期)。

如上所述,另一个重要领域是检测代码库中更改的位置。我真的很喜欢Atlassian Fisheye。除了非常擅长在任何时间点搜索提交消息(例如错误 ID)或文件内容外,它还允许我轻松查看指标:

  • 按目录和子目录的行数
  • 任何时间点或特定目录和/或文件中的提交者
  • 提交模式,包括时间和源代码中的位置
于 2012-10-22T09:39:33.767 回答
10

恐怕你大部分时间都靠自己。

如果您有一套不错的测试,请查看代码覆盖率和死代码。

如果您有一个不错的配置文件设置,请使用它来了解更多使用的内容。

最后,您似乎对扇入/扇出分析更感兴趣,我不知道 Python 有什么好的工具,主要是因为静态分析对于动态语言非常不可靠,到目前为止我没有看不到任何统计分析工具。

我认为这些信息在 JIT 编译器中是可用的——无论(函数、参数类型)在缓存(编译)中,这些都是最常用的。您是否可以从例如 PyPy 中获取这些数据,我真的不知道。

于 2012-09-30T16:45:34.777 回答
5

源代码控制工具可以很好地指示经常更新的模块 - 通常指示故障点。

如果您没有源代码控制但项目是从共享位置运行的,请删除所有pycache文件夹或 .pyc 文件。随着时间的推移/使用不足,观察哪些文件被重新创建以表明它们的使用。

分析从特定入口点运行时打印的 Python 导入

python -v entry_point

可能会深入了解正在使用哪些模块。虽然如果您有已知的接入点,您应该尝试覆盖模块。

对于更具侵入性的解决方案,请考虑设置项目范围的日志记录。您可以很容易地记录指标,甚至在分布式程序上也是如此。

于 2012-10-17T08:33:02.353 回答
5

我同意其他人的观点,因为我还没有遇到一个好的 Python 运行时分析工具可以做到这一点。有一些方法可以处理它,但没有一个是微不足道的。

我认为,最强大的方法是获取 Python 源代码并使用某种内置的运行时日志重新编译二进制文件。这样您就可以将其滑入现有环境,而无需对项目进行任何代码更改。当然,这并不是一件小事,但它有一个好处,你可能有一天能够将它合并到后备箱中,以供后代使用,等等。

对于非重新编译方法,我首先要看的是配置文件库的确定性分析部分

您如何实现它在很大程度上取决于您的环境是如何设置的。您是否有许多单独的脚本和项目彼此独立运行,或者只有一个主要脚本或模块或包被其他人使用,您只是想知道可以删减其中的哪些部分以使维护更容易?它是一次加载,永远运行的设置,还是您只是按某种计划以原子方式运行脚本的情况?

您可以实现项目范围的日志记录(如@Hardbyte 的答案中所述),但这需要遍历项目并将日志记录行添加到您的所有代码中。如果你这样做,你也可以使用内置的profiler,我想。

于 2012-10-17T18:36:51.707 回答
2

看看sys.setprofile:它允许您安装分析器功能。

它的用法在http://docs.python.org/library/profile.html#profile中有详细说明,这里是一个快速入门。

如果您无法分析您的应用程序,您将被绑定到 cooverage 方法。

您可能会看到的另一件事是装饰器,您可以编写一个调试 装饰器,并将其应用于您怀疑的一组函数。看看这里,看看如何将装饰器应用到整个模块。

您还可以查看python call graph,虽然它不会生成您想要的内容,但它会显示一个函数调用另一个函数的频率:

如果您的代码在用户输入上运行,这将很难,因为您必须模拟“典型”用法。

没有更多要告诉你的,只要记住profiling作为关键字。

于 2012-10-19T16:08:16.003 回答
1

Pylint 有时会发出警告(经过仔细考虑)是不合理的。在这种情况下,如果无法重构代码以不触发警告,则使用特殊#pylint: disable=X0123注释(其中 X0123 是实际的错误/警告消息编号)很有用。

我想第二次 Hardbyte 提到使用您的源代码控制日志来查看哪些文件最常更改。

如果您正在使用已安装 并安装的系统find,则以下是检查哪个文件导入了什么的方法;grepsort

find . -name '*.py' -exec grep -EH '^import|^from .* import' {} \+| sort |less

在所有文件中查找最受欢迎的导入;

find . -name '*.py' -exec grep -Eh '^import|^from .* import' {} \+ | sort | less

这两个命令应该可以帮助您从项目中找到最常用的模块。

于 2012-10-21T12:49:20.147 回答