SQLAlchemy 和 pylint

SQLAlchemy and pylint

SQLAlchemy 似乎给了我很多我无法解决的 pylint 错误。

第一个问题是每个table必须定义为一个新的class。

示例:

class Person(BASE):
    """Person Table Definition"""
    __tablename__ = 'person'
    id = Column(Integer, primary_key=True)
    name = Column(String(30))

...导致这些错误 对于每个 table 我定义:

W: 20, 0: Class has no __init__ method (no-init)
R: 20, 0: Too few public methods (0/2) (too-few-public-methods)

第二个问题是为 SQLAlchemy engineBASE 构造使用全局变量。我不确定如何重构此代码以使这些变量不是全局变量,因为必须将参数 BASE 传递到上面的 table class 定义中。

BASE = sqlalchemy.ext.declarative.declarative_base()
global engine
...
def create_sqla_engine():
    """Create the SQLA engine"""
    global engine
    engine = create_engine('mysql+mysqlconnector://root:@127.0.0.1:3306/sqlalchemy_example')

我是 python 的新手,但这看起来很难看。 pylint 也抱怨它:

C: 51, 0: Invalid constant name "engine" (invalid-name)

最后,pylint 认为我没有使用我在这段代码中明确使用的导入。

W: 15, 0: Unused declarative_base imported from sqlalchemy.ext.declarative (unused-import)
W: 16, 0: Unused sessionmaker imported from sqlalchemy.orm (unused-import)

...为什么? pylint 与 python3 不兼容吗?我应该在使用的方法中导入我需要的模块,而不是在文件顶部吗?

SQLAlchemy 对 pylint 不是很友好。

你的问题有几点。

1。 public 方法太少

这个错误经常出错,看这里:What does pylint's "Too few public methods" message mean

2。未使用的导入

Pylint 在这种情况下是正确的!如果您导入 declarative_base,您可以直接使用它:declarative_base(...),而不是通过 sqlalchemy.ext.declarative.declarative_base()

通常 - 如果未使用导入,请尝试将其删除并检查您的代码(和单元测试,注意 doctests!)是否仍然有效。如果是这样,则导入确实未被使用。

TL;DR - 是的,您使用的是 code,但没有使用导入的 names.

3。无效常量名称

Pylint 在这种情况下是错误的,但原则上是正确的。

(我花了很多时间说服甚至体面的程序员只覆盖 Pylint 的 const-rgx 设置...)。

基本上,Pylint 认为每个全局变量都是常量。在你的情况下它不是。因此,pylint 试图阻止您使用全局变量。

此外,您不应该在函数之外(在全局范围内)编写 global engine。它应该是这样的:

engine = None

Pylint 仍然会抱怨错误的常量名称。您可以明确地使此警告静音。 (我不建议将其重命名为 ENGINE

4。 (额外)SQLAlchemy 查询构建

我发现了这个问题,因为我想看看 pylint 在 SQLAlchemy 条件下的建议。

与 Django 模型不同,SQLAlchemy 使用比较 == 来获得相等条件(Django 的 field_gt=5 实际上很笨拙,随着时间的推移我不得不喜欢 SQLAlchemy 的方式)。但是Pylint会抱怨:

session.query(AlarmState).filter(AlarmState.is_default == True).one()

给予

C0121: comparison to True should be just 'expr' or 'expr is True'

一切都很好 - 在这种情况下我们真的可以写:

session.query(AlarmState).filter(AlarmState.is_default).one()

而且很好。

但是,怎么样:

session.query(AlarmState).filter(AlarmState.is_default == False).all()

好吧,我们得到:

C0121: comparison to False should be just 'not expr' or 'expr is False'

现在怎么办?这不起作用:session.query(AlarmState).filter(not AlarmState.is_default .all()!!! - 它似乎按 False 条件和 returns 空集过滤。同样在这里:sess.query(AlarmState).filter(AlarmState.is_default is False).all().

我找到了解决方法 - 你实际上可以写:

session.query(AlarmState).filter(AlarmState.is_default.__eq__(False)).all()

两者兼而有之:

  • 给出正确的结果
  • 不引发 Pylint 通知

我对此感觉不太好。这是在用这个愚蠢的工具玩猫捉老鼠的游戏。 我想知道其他人对此做了什么,这就是我来到这里的原因。

编辑 - 好的,我找到了 "right" 的方法...

如何将列与 False 进行比较(没有投诉)?

from sqlalchemy import not_
session.query(AlarmState).filter(not_(AlarmState.is_default)).all()

这就是 not_ 可能用于...