在您的应用程序中识别“敏感”代码

21

想要改善一个相当大的Python项目的质量。我对PyLint提供的警告类型感到满意,但是它们太多了,在大型组织中难以强制执行。此外,我认为某些代码比其他代码更关键/敏感,涉及下一个错误可能出现的位置。例如,我想花更多时间验证一个被100个模块使用的库方法,而不是2年前最后一次接触并且可能不会在生产中使用的脚本。另外,知道经常更新的模块也很有趣。

是否有人熟悉Python或其他工具,可以帮助进行这种类型的分析?

6个回答

15
你的问题与我在SQA https://sqa.stackexchange.com/a/3082 上回答的问题类似。这个问题涉及到Java,使得工具更容易使用,但是我有一些以下建议。
其他答案中有一些人认为Python没有好的运行时工具。我在几个方面上不同意:
  1. 覆盖率工具非常好用
  2. 基于我在Java工具方面的经验,Python中的静态和动态分析工具比强类型、不太动态的语言要弱,但是会足够好地提供给你很好的启发式方法。除非你使用了异常数量的动态特性(包括添加和删除方法,拦截方法和属性调用,玩弄导入,手动修改命名空间)- 在这种情况下,你可能遇到的任何问题都可能与这种动态性有关...
  3. Pylint可以解决一些简单的问题,并且不会检测到动态类/实例修改和装饰器的问题,因此度量工具不测量这些问题也无所谓。
  4. 在任何情况下,你可以有用地关注的内容远不止依赖图。

选择代码的启发式方法

我发现在选择改进代码时需要考虑许多不同因素,并且这些因素可以单独或共同起作用。记住,最初你只需要找到一条有成效的工作线索-你不需要在开始之前找到最糟糕的代码。
运用你的判断力。
经过几次代码循环之后,你将获得大量信息,并且更有可能继续你的工作-如果确实需要更多的工作。
话虽如此,以下是我的建议:
对业务价值高:例如可能会给公司带来巨大损失的任何代码。其中许多可能很明显或广为人知(因为它们很重要),或者可以通过在启用运行时分析器的系统上运行重要用例来检测到。我使用Coverage
静态代码指标:有很多指标,但是我们关心的是: 请注意,这些工具是基于文件的。考虑到你提到该项目本身有数百个模块(文件),这可能已经足够了。
频繁更改的代码很可疑。代码可能存在许多缺陷,并且根据经验可能会继续存在。代码正在进行功能开发的更改(在您的版本控制系统中进行了大量修订)。
使用VCS可视化工具查找变化区域,如本答案后面讨论的那些。
未覆盖的代码:未经测试的代码。
如果您可以运行单元测试、其他自动化测试和典型用户测试并获得覆盖率,请查看覆盖率几乎为零的包和文件。没有覆盖率的两个逻辑原因:
1. 代码是必需的(而且重要),但根本没有测试(至少不是自动测试)。这些区域的风险极高。 2. 代码可能未被使用,是删除的候选项。
询问其他开发人员。
你也许会感到惊讶,通过和资深开发人员一起喝咖啡,你可以获取到有关代码“气味”的指标。我敢打赌,如果有人清理了一个只有最勇敢的人才会涉足的代码库中的肮脏区域,他们会非常高兴。
可见性-检测时间变化
我假设您的环境具有分布式版本控制系统(例如Git或Mercurial)或至少有一个版本控制系统(例如SVN)。我希望您还使用某种问题或错误跟踪器。如果是这样,那么有大量信息可以使用。如果开发人员可靠地附带注释和问题号,则更好。但是如何将其可视化和使用?
虽然您可以在单个桌面上解决问题,但建议设置连续集成(CI)环境,可能使用诸如Jenkins之类的工具。为了简洁起见,从现在开始我将假设使用Jenkins。Jenkins配备了大量插件,对于代码分析非常有帮助。我使用: 这让我能够看到随时间变化的变化,并且我可以从那里深入了解。例如,假设一个模块中的PyLint违规开始增加 - 我有增加的证据,并且我知道发生这种情况的包或文件,因此我可以找出谁参与其中并与他们交谈。
如果您需要历史数据,并且刚刚安装了Jenkins,请尝试运行一些手动构建,从项目开始并向前跳跃一系列时间,直到现在。您可以从VCS中选择里程碑发布标记(或日期)。
另一个重要领域,如上所述,是检测代码库中更改的位置。我真的很喜欢Atlassian Fisheye。除了在任何时间点搜索提交消息(例如bug id)或文件内容外,它还允许我轻松查看指标:
  • 按目录和子目录的行数
  • 任何时间点或特定目录和/或文件的提交者
  • 提交的模式,既按时间,也按源代码中的位置

10

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

如果你有一套不错的测试,就看测试覆盖率和无用代码。

如果你有一个不错的分析设置,就用它来一窥哪些被使用得更多。

最后,似乎你更感兴趣的是扇入/扇出分析,我不知道有哪些好的Python工具,主要是因为对于动态语言而言静态分析极其不可靠,至今我还没有看到任何统计分析工具。

我认为这些信息在JIT编译器中可以获取——缓存(已编译)的内容(函数、参数类型)是最常用的。关于是否可以从PyPy等工具中获取这些数据,我真的毫不清楚。


@JonasWielicki:我只是想问,在“abusing”中,“ab”在哪里? - ted
@ted,根据我的理解,分析器通常用于性能分析。可能我没有理解你的笑话。 - Jonas Schäfer
1
@JonasWielicki:我认为性能分析也是热点分析的首选工具。我们有性能分析和跟踪。而且,该操作只关心代码的调用次数而不关心顺序,因此我认为性能分析是正确的工具。 - ted
显然,这是正确的工具,因为它在这种情况下可以满足你的需求。我以前从未想过使用分析器来做这件事。 - Jonas Schäfer

5

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

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

通过特定入口点运行时打印的Python导入进行分析。

python -v entry_point

可以提供一些有关使用的模块的见解。但是,如果您已知道访问点,应该尝试使用覆盖率模块。

对于更具侵入性的解决方案,请考虑设置项目范围的日志记录。您可以轻松记录指标,即使在分布式程序中也是如此。


5
我同意其他人的看法,即我尚未遇到适用于Python的良好运行时分析工具来完成此操作。有一些方法可以解决这个问题,但没有一种是简单的。
我认为最健壮的方法是获取Python源代码并重新编译二进制文件以包含某种内置的运行时日志记录。这样,您就可以将其轻松地插入现有环境中,而无需对项目进行任何代码更改。当然,这并不是一件容易的事情,但它的优点是您可能有一天能够将其合并回主干以供未来的使用。
对于非重新编译的方法,我首先会查看剖析库的确定性剖析部分
如何实施将严重依赖于您的环境设置。您是否有许多独立运行的脚本和项目,还是只有一个主要脚本或模块或包被所有其他人使用,并且您只想知道可以修剪哪些部分以使维护更容易?它是一种一次加载,永久运行的设置,还是一种您只需按某种时间表原子地运行脚本的情况?
您可以实现项目级别的日志记录(如 @Hardbyte 的回答中所提到的),但这需要遍历整个项目并向所有代码添加日志记录行。如果您这样做,您可能会考虑使用内置的 profiler 来完成。

2
看一下 sys.setprofile:它允许你安装一个分析器函数。
使用方法在http://docs.python.org/library/profile.html#profile中有详细介绍,如果想快速上手请看这里
如果无法对应用程序进行分析,则只能使用覆盖率方法。
你还可以看一下装饰器,可以编写一个调试装饰器,并将其应用于怀疑的函数集。点击这里了解如何将装饰器应用于整个模块。
你也可以看一下python调用图,虽然它无法生成你需要的内容,但会显示一个函数调用另一个函数的频率:
如果你的代码根据用户输入运行,则会很困难,因为你需要模拟“典型”使用情况。
没什么好说的了,只要记住 profiling 关键字。

1

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

我想强调Hardbyte提到的使用源代码控制日志查看哪些文件经常更改的方法。

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

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

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

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

这两个命令可以帮助您找到项目中使用最频繁的模块。

这是一个非常肤浅的“最常用”的定义,不是吗? - Dima Tisnek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接