在 Django 中使用 Pylint

我非常希望将 pylint集成到构建过程中 我的 python 项目,但我遇到了一个表演停止: 其中一个 我发现非常有用的错误类型—— : < code > E1101: *% s% r has no% r Member * ——在使用常见的 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 源代码,请指出具体细节:)

有关我使用 pycheckerpyflakes时遇到的问题的摘要,请参阅 这里-它们已被证明对于一般使用来说远远不稳定。(在 pychecker 的例子中,崩溃源自 pychecker 代码——不是源代码,而是加载/调用。)

59465 次浏览

因为 pylint 是如何工作的(它检查源代码本身,而不让 Python 实际执行它) ,所以 pylint 很难弄清楚元类和复杂的基类实际上是如何影响一个类及其实例的。在这方面,‘ pycheck’工具要好一些,因为它的 是的实际上允许 Python 执行代码; 它导入模块并检查结果对象。但是,这种方法还有其他问题,因为它实际上允许 Python 执行代码: -)

您可以扩展 pylint 来教它 Django 的神奇用法,或者让它更好地理解元类或复杂的基类,或者在检测到一个或多个它不完全理解的特性后忽略这些情况。我不认为这会特别容易。还可以通过源代码中的特殊注释、命令行选项或。Pylintrc 文件。

试试用

pylint --ignored-classes=Tags

如果可行,添加所有其他 Django 类——可以使用一个脚本,比如 python: P

--ignore-classes的文档如下:

--ignored-classes=<members names>
成员的类名列表 不应该检查属性 (对于具有属性的类很有用 [当前:% default ]

我应该补充一点,在我看来,这不是一个特别优雅的解决方案,但它应该是有效的。

我放弃使用 pylint/pychecker,转而使用带有 Django 代码的 pyflakes ——它只是尝试导入模块并报告它发现的任何问题,比如未使用的导入或未初始化的本地名称。

这不是一个解决方案,但是您可以将 objects = models.Manager()添加到 Django 模型中,而不改变任何行为。

我自己只使用 pyflakes,主要是由于 pylint 中的一些愚蠢的默认值和我的懒惰(不想查找如何更改默认值)。

到目前为止,我还没有找到真正的解决办法,只能想办法:

  • 在我们公司,我们需要一个皮林特 得分 > 8。这允许编码 皮林特不理解的行为 同时确保代码不是 太“不寻常”了。到目前为止,我们还没有看到 E1101把我们关起来的任何例子 从达到8分或 再高点。
  • 我们的“检查”目标 过滤掉“ for 没有‘ object’” 成员”消息,以删除大部分 皮林特造成的干扰 理解姜戈。

我使用以下代码: pylint --generated-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

最后两个是专门为姜戈准备的。

请注意,有一个 PyLint 0.21.1中的 bug需要修补程序来完成这项工作。

编辑: 在做了一些修改之后,我决定修改一下 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

在 bug 报告中提到的修复之后(例如,在第129行)。

快乐的日子!

解决方案在这个 另一个问题它简单地添加 开始吧到您的标签类。丑陋,但工程。

不要通过添加 ignoresgenerated-members来禁用或削弱 Pylint 功能。
使用一个积极开发的 Pylint 插件 明白 Django。
这个用于 Django 的 Pylint 插件工作得非常好:

pip install pylint-django

在运行 pylint 时,将以下标志添加到命令中:

--load-plugins pylint_django

详细的博客文章 给你

如果使用 VisualStudio 代码,请执行以下操作:

pip install pylint-django

并添加到 VSC 配置:

"python.linting.pylintArgs": [
"--load-plugins=pylint_django"
],

对于 neovim & vim8使用 w0rp's ale插件。如果你已经安装一切正确,包括 w0rp's alepylintpylint-django。在你的 vimrc添加以下行 & 有趣的开发网络应用程序使用 django。 谢谢。

let g:ale_python_pylint_options = '--load-plugins pylint_django'

对于 heroku 用户,您还可以使用 Tal Weiss 对这个问题的回答使用以下语法来使用 pylint-django 插件运行 pylint (用应用程序/包替换 timekeeping) :

# run on the entire timekeeping app/package
heroku local:run pylint --load-plugins pylint_django timekeeping


# run on the module timekeeping/report.py
heroku local:run pylint --load-plugins pylint_django timekeeping/report.py


# With temporary command line disables
heroku local:run pylint --disable=invalid-name,missing-function-docstring --load-plugins pylint_django timekeeping/report.py

注意: 如果不指定项目/包目录,我就无法运行。

如果 E5110: Django was not configured.有问题,也可以按照以下方式进行调用,试图解决这个问题(同样,将 timekeeping更改为 app/package) :

heroku local:run python manage.py shell -c 'from pylint import lint; lint.Run(args=["--load-plugins", "pylint_django", "timekeeping"])'


# With temporary command line disables, specific module
heroku local:run python manage.py shell -c 'from pylint import lint; lint.Run(args=["--load-plugins", "pylint_django", "--disable=invalid-name,missing-function-docstring", "timekeeping/report.py"])'