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

时间:2012-09-27 04:32:05

标签: python code-analysis

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

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

6 个答案:

答案 0 :(得分:15)

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

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

  1. 覆盖工具效果很好
  2. 根据我在Java工具方面的经验,Python中的静态和动态分析工具比强类型的动态性较弱的语言弱,但的工作效果要好得多,在这里为您提供良好的启发式方法。除非您使用异常大的病理数量的动态功能(包括添加和删除方法,拦截方法和属性调用,使用导入,手动修改命名空间) - 在这种情况下,您遇到的任何问题都可能与此动态相关联。
  3. Pylint选择了更简单的问题,并且不会检测动态类/实例修改和装饰器的问题 - 因此公制工具不能测量这些问题并不重要
  4. 在任何情况下,您可以通过依赖图来确定有用的焦点。
  5. 用于选择代码的启发式

    我发现选择改进代码有很多不同的考虑因素,这些代码可以单独使用,也可以一起使用。请记住,首先,您需要做的就是找到一份富有成效的工作方式 - 在开始之前,您不需要找到绝对最差的代码。

    使用你的判断。

    经过代码库几个周期后,您将获得大量信息,并且可以更好地继续工作 - 如果确实需要做更多的事情。

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

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

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

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

    频繁更改:经常更改的代码非常可疑。代码可以:

    • 历史上有许多缺陷,而且凭经验可能会继续这样做
    • 正在进行功能开发的更改(VCS中的大量修订)

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

    未覆盖的代码:代码未涵盖的代码。

    如果你运行(或可以运行)你的单元测试,你的其他自动化测试和覆盖范围的典型用户测试,看看没有覆盖的旁边的包和文件。没有报道的原因有两个:

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

    询问其他开发者

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

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

    我假设您的环境有DVCS(例如Git或Mercurial)或至少有VCS(例如SVN)。我希望您也使用某种问题或错误跟踪器。如果是这样,那么可获得大量信息。如果开发人员可靠地签入评论和发布号码,情况会更好。但是你如何想象它并使用它呢?

    虽然您可以在单个桌面上解决问题,但建立持续集成(CI)环境可能是个好主意,可能使用Jenkins之类的工具。为了简短回答,我将从现在开始假设詹金斯。 Jenkins附带了大量的插件,可以帮助进行代码分析。我用:

    这让我可以看到更改随着时间的推移,我可以从那里钻取。例如,假设PyLint违规在模块中开始增加 - 我有增加的证据,并且我知道发生这种情况的包或文件,因此我可以找出涉及的人并与他们交谈。 / p>

    如果您需要历史数据并且刚刚安装了Jenkins,请查看是否可以运行一些从项目开始时开始的手动构建,并在当前向前进行一系列跳转。您可以从VCS中选择里程碑版本标记(或日期)。

    如上所述,另一个重要领域是检测代码库中的变化轨迹。我真的很喜欢Atlassian Fisheye。除了非常善于在任何时间点搜索提交消息(例如bug id)或文件内容外,它还允许我轻松查看指标:

    • 按目录和子目录划分的行数
    • 任何时间点或特定目录和/或文件中的提交者
    • 提交的模式,包括时间和源代码中的位置

答案 1 :(得分:10)

我担心你大多是靠自己。

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

如果您有一个不错的分析设置,请使用它来瞥一眼使用的内容。

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

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

答案 2 :(得分:5)

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

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

分析使用

从特定入口点运行时打印的Python导入
python -v entry_point

可以深入了解正在使用哪些模块。虽然如果您有已知的接入点,则应尝试使用coverage模块。

对于更具侵入性的解决方案,请考虑设置项目范围的日志记录。您甚至可以通过分布式程序轻松地记录度量标准。

答案 3 :(得分:5)

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

我认为最强大的是获取Python源代码并使用某种内置的运行时日志记录重新编译二进制文件。这样您就可以将其滑入现有环境,而无需对项目进行任何代码更改。 当然,这并不是一件轻而易举的事情,但它有一个额外的好处,就是你有朝一日能够将它合并回后代,而不是后代。

对于非重新编译方法,我看的第一个地方是the profile library's deterministic profiling section

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

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

答案 4 :(得分:2)

查看sys.setprofile:它允许您安装探查器功能。

其用法详见http://docs.python.org/library/profile.html#profile,快速启动here

如果您无法对您的申请进行简介,您将受到同样的覆盖。

您可能要看的另一件事是装饰器,您可以编写debugging decorator,并将其应用于您怀疑的一组函数。拿到here以查看如何将装饰器应用于整个模块。

您可能还会看一下python call graph,但它不会产生您想要的效果,它会显示一个函数调用另一个函数的频率:

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

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

答案 5 :(得分:1)

Pylint有时会发出警告(仔细考虑后)是不合理的。在这种情况下,如果代码无法重构以不触发警告,则使用特殊的#pylint: disable=X0123注释(其中X0123是actual error/warning message number)很有用。

我想提及Hardbyte提到使用源代码控制日志来查看最常更改的文件。

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

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

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

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

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