我有一个像这样定义的 sqlalchemy 表
from sqlalchemy.sql.schema import Table
my_table = Table(
"my_table",
metadata,
Column("my_id", BigInteger(), primary_key=True),
...
)
我正在尝试检查此实例以获取创建它的模块。我曾尝试使用sqlalchemy.inspect(my_table).__module__
, my_table.__module__
, ,inspect.getmodule(my_table)
但是,所有三个都返回sqlalchemy.sql.schema
它Table
是定义的模块而不是定义的模块my_table
。
如何检索已实例化的模块的名称my_table
?
您可以通过子类化来添加功能Table
。在 SQLAlchemy 中,Table
专门覆盖Table.__init__()
以使其成为无操作:
def __init__(self, *args, **kw):
"""Constructor for :class:`~.schema.Table`.
This method is a no-op. See the top-level
documentation for :class:`~.schema.Table`
for constructor arguments.
"""
# __init__ is overridden to prevent __new__ from
# calling the superclass constructor.
关键是它不会调用super().__init__()
,因此 sqlalchemy 可以控制实例化,无论您做什么,都需要维护。
from sqlalchemy.sql.schema import Table
class MyTable(Table):
def __init__(self, *args, **kwargs):
self._where_am_i = __file__
my_table = MyTable(
"my_table",
metadata,
Column("my_id", BigInteger(), primary_key=True)
)
在这种情况下,MyTable.__init__()
仍然阻塞超类构造函数,但它也向实例添加了一个属性,该属性将是类在其中实例化的模块的名称。我特别选择了一个_where_am_i
不太可能被 sqlalchemy 覆盖的晦涩属性名称 ( ) 并使用__file__
返回模块的路径(但您可以根据需要进行任何设置)。
我测试过插入和选择仍然有效:
import logging
from sqlalchemy.sql import select
logging.getLogger('sqlalchemy.engine').setLevel(logging.INFO)
logging.basicConfig(level=logging.INFO)
Base.metadata.drop_all(engine)
Base.metadata.create_all(engine)
conn = engine.connect()
conn.execute(my_table.insert(), [{"my_id": i} for i in range(1, 6)])
s = select([my_table])
result = conn.execute(s)
for row in result:
print(row)
# (1,)
# (2,)
# (3,)
# (4,)
# (5,)
和实例化位置:
print(my_table._where_am_i) # 53302898.py (that's the name of my module).
外部模块:
# external_module.py
from sqlalchemy_app import Base
from sqlalchemy.sql.schema import Table
from sqlalchemy import Column, BigInteger
metadata = Base.metadata
class MyTable(Table):
def __init__(self, *args, **kwargs):
self._where_am_i = __file__
my_table = MyTable(
"my_table",
metadata,
Column("my_id", BigInteger(), primary_key=True)
)
和:
# 53302898.py
from external_module import my_table
if __name__ == '__main__':
print(my_table._where_am_i) # prints C:\Users\peter_000\OneDrive\git\test\external_module.py
请注意它如何返回第一个测试中的相对文件路径和外部模块测试中的绝对文件路径。你可以在这里阅读:Python __file__ 属性是绝对的还是相对的?但是您可以使该_where_am_i
属性返回适合您的应用程序所需的任何内容。
编辑上述解决方案需要在形成实例的模块内对类进行子Table
类化,否则它将固定类实例化的模块,而不是实例。如果您只想在项目中子类化一次,则需要将位置传递给构造函数。Table
这有效:
class MyTable(Table):
def __init__(self, *args, _where_am_i=None, **kwargs):
self._where_am_i = _where_am_i
...但是您在实例化时收到警告:
SAWarning: Can't validate argument '_where_am_i'; can't locate any SQLAlchemy dialect named '_where'
.
为避免这种情况,您必须覆盖 sqlalchemy 的备用构造函数 ,去掉Table._init()
location 参数,然后委托备份链:
class MyTable(Table):
def _init(self, *args, _where_am_i=None, **kwargs):
self._where_am_i = _where_am_i
super()._init(*args, **kwargs)
从外部模块导入:
# 53302898.py
from external_module import MyTable
my_table = MyTable(
"my_table",
metadata,
Column("my_id", BigInteger(), primary_key=True),
_where_am_i = __file__
)
if __name__ == '__main__':
print(my_table._where_am_i) # 53302898.py
以上所有测试仍然通过。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句