消除 SQLAlchemy 警告

chr*_*ley 8 python postgresql sqlalchemy

我正在将一个遗留项目切换为自动生成 alembic 迁移,它有一些 sqlalchemy 无法识别的索引。当我运行时,alembic revision --autogenerate migration_name会创建一个空迁移(因为我已经解决了所有其他不一致问题),但我收到 8 个警告,例如:

/project/.venv/lib/python3.6/site-packages/sqlalchemy/dialects/postgresql/base.py:3328: SAWarning: Skipped unsupported reflection of expression-based index idx_name
  "expression-based index %s" % idx_name
Run Code Online (Sandbox Code Playgroud)

在 postgres 中,我查找索引定义,如下所示:

/project/.venv/lib/python3.6/site-packages/sqlalchemy/dialects/postgresql/base.py:3328: SAWarning: Skipped unsupported reflection of expression-based index idx_name
  "expression-based index %s" % idx_name
Run Code Online (Sandbox Code Playgroud)

读完这篇文章后,我尝试在模型定义之后添加索引并添加到__table_args__​​ .

mydb=# SELECT tablename, indexdef FROM pg_indexes WHERE schemaname = 'public' AND indexname = 'idx_name';
 tablename |                                   indexdef                                    
-----------+-------------------------------------------------------------------------------
 plan      | CREATE UNIQUE INDEX idx_name ON public.plan USING btree (lower((name)::text))
(1 row)
Run Code Online (Sandbox Code Playgroud)
# add it after model definition
class Plan(db.Model):
    __table_name__ = 'plan'
    # ...

db.Index('this_does_nothing_in_autogenerate', func.lower(Plan.__table__.c.name), unique=True)
Run Code Online (Sandbox Code Playgroud)

这两项更改都添加了警告(如下所示),创建空迁移,并且不删除原始警告。我知道 sqlalchemy+alembic 无法处理这些更复杂的索引,但是有什么方法可以消除警告吗?

# Warning for first method
/home/chriscauley/develop/kennel/.venv/lib/python3.6/site-packages/alembic/util/messaging.py:69: UserWarning: autogenerate skipping functional index this_does_nothing_in_autogenerate; not supported by SQLAlchemy reflection
  warnings.warn(msg)

# warning for second __table_args__ method
/home/chriscauley/develop/kennel/.venv/lib/python3.6/site-packages/alembic/util/messaging.py:69: UserWarning: autogenerate skipping functional index idx_this_also_does_nothing; not supported by SQLAlchemy reflection
  warnings.warn(msg)
Run Code Online (Sandbox Code Playgroud)

fox*_*lue 4

是的,有几种方法可以消除警告。如果您知道警告在哪里发出,您可以创建一个上下文管理器来捕获该发出的函数。如 std-lib 的文档所示

import warnings

def fxn():
    warnings.warn("deprecated", DeprecationWarning)

with warnings.catch_warnings():
    warnings.simplefilter("ignore")
    fxn()
Run Code Online (Sandbox Code Playgroud)

否则,不推荐的方法是将以下内容添加到主脚本中:

import warnings

warnings.simplefilter("ignore")
Run Code Online (Sandbox Code Playgroud)

忽略警告的更合适的方法(在这里向我指出)是首先检查警告选项标志,这允许您通过使用该标志运行代码来重新打开警告-W(例如python -W):

import sys
import warnings

if not sys.warnoptions:
    warnings.simplefilter("ignore")
Run Code Online (Sandbox Code Playgroud)

最后回答你的问题。该warnings.filterwarnings方法有一个module参数,可以让您指定想要抑制警告的模块。在你的情况下可能是:

import warnings

warnings.filterwarnings("ignore", category=UserWarning, module="alembic.util.messaging")
Run Code Online (Sandbox Code Playgroud)