在Django中使用Pylint

时间:2020-03-06 14:33:00  来源:igfitidea点击:

我非常想将pylint集成到
我的python项目,但遇到了一个显示停止器:
我认为非常有用的错误类型-:E1101:%s%r没有%r
成员
`-使用常见的django字段时始终报告错误,
例如:

E1101:125:get_user_tags: Class 'Tag' has no 'objects' member

这是由以下代码引起的:

def get_user_tags(username):
   """
   Gets all the tags that username has used.

   Returns a query set.
   """
   return Tag.objects.filter(  ## This line triggers the error.
       tagownership__users__username__exact=username).distinct()

# Here is the Tag class, models.Model is provided by Django:
class Tag(models.Model):
   """
   Model for user-defined strings that help categorize Events on
   on a per-user basis.
   """
   name = models.CharField(max_length=500, null=False, unique=True)

   def __unicode__(self):
       return self.name

如何调整Pylint以适当考虑诸如对象之类的字段? (我也研究了Django的源代码,但我一直无法找到`objects'的实现,因此我怀疑它不是"仅仅"一个类字段。另一方面,我对python还是相当陌生的,所以我很可能已经忽略了一些东西。)

编辑:我发现告诉pylint不要警告这些警告的唯一方法是阻止所有类型的错误(E1101),这是不可接受的解决方案,因为(在我看来)这是一个非常有用的错误。如果还有另一种方法,而又不增加pylint的来源,请给我指出细节:)

有关我使用pychecker和pyflakes遇到的问题的摘要,请参见此处,事实证明它们对于一般用途而言非常不稳定。 (在pychecker的情况下,崩溃源于pychecker代码-而不是它正在加载/调用的源。)

解决方案

由于pylint的工作方式(它在不让Python实际执行的情况下检查源代码本身)使pylint很难弄清楚元类和复杂的基类如何实际上影响一个类及其实例。在这方面," pychecker"工具要好一些,因为它确实允许Python执行代码。它导入模块并检查生成的对象。但是,该方法还有其他问题,因为它确实允许Python执行代码:-)

我们可以扩展pylint来教它有关Django所使用的魔术的知识,或者使它更好地理解元类或者复杂的基类,或者在检测到一个或者多个它不太了解的功能之后忽略这些情况。我认为这不会特别容易。我们还可以通过源代码中的特殊注释,命令行选项或者.pylintrc文件,告诉pylint不要警告这些事情。

尝试与运行pylint

pylint --ignored-classes=Tags

如果可行,请使用脚本添加所有其他Django类,例如python:P

--ignore-classes的文档是:

--ignored-classes=<members names>

  List of classes names for which member
  attributes should not be checked
  (useful for classes with attributes
  dynamicaly set). [current: %default]

我认为这并不是一个特别优雅的解决方案,但它应该可以工作。

我从使用pylint / pychecker辞职,转而将pyflakes与Django代码一起使用,它只是尝试导入模块并报告发现的任何问题,例如未使用的导入或者未初始化的本地名称。

这不是解决方案,但是我们可以在不更改任何行为的情况下将objects = models.Manager()添加至Django模型。

我自己只使用pyflakes,主要是因为我的部分pylint和懒惰有一些愚蠢的默认设置(不想查看如何更改默认设置)。

到目前为止,我没有找到真正的解决方案,但是可以解决:

  • 在我们公司,我们要求pylint分数>8. 这允许pylint无法理解编码实践,同时确保代码不太"异常"。到目前为止,我们还没有看到E1101阻止我们达到8分或者更高分数的情况。
  • 我们的" make check"目标过滤掉" for has no'objects member"消息,以消除由于pylint不了解Django引起的大部分干扰。

我使用以下命令:pylint --generation-members = objects

django-lint是一个不错的工具,它使用django特定的设置包装pylint:http://chris-lamb.co.uk/projects/django-lint/

github项目:https://github.com/lamby/django-lint

我的〜/ .pylintrc包含

[TYPECHECK]
generated-members=REQUEST,acl_users,aq_parent,objects,_meta,id

最后两个是专门针对Django的。

请注意,PyLint 0.21.1中存在一个错误,需要对其进行修补才能使其正常工作。

编辑:弄乱了一点之后,我决定对PyLint进行一点修改,以允许我将以上内容扩展为:

[TYPECHECK]
generated-members=REQUEST,acl_users,aq_parent,objects,_meta,id,[a-zA-Z]+_set

我只是添加:

import re
    for pattern in self.config.generated_members:
        if re.match(pattern, node.attrname):
            return

在错误报告中提到的修复程序之后(即在第129行)。

快乐的时光!