从应用程序代码内部使用 Alembic API

新手上路,请多包涵

我将 SQLite 用作我的基于 PySide 的桌面应用程序的应用程序文件格式(请参阅 此处 了解您想要这样做的原因)。也就是说,当用户使用我的应用程序时,他们的数据将保存在他们机器上的单个数据库文件中。我正在使用 SQLAlchemy ORM 与数据库进行通信。

当我发布应用程序的新版本时,我可能会修改数据库模式。我不希望用户每次更改架构时都必须丢弃他们的数据,因此我需要将他们的数据库迁移到最新格式。此外,我经常创建临时数据库来保存数据子集以供某些外部进程使用。我想用 alembic 创建这些数据库,以便用正确的版本标记它们。

我有几个问题:

  • 有没有办法从我的 Python 代码中调用 alembic?我认为必须将 Popen 用于纯 Python 模块很奇怪,但文档只是从命令行使用 alembic。主要是,我需要将数据库位置更改为用户数据库所在的位置。

  • 如果那不可能,我是否可以在不编辑 .ini 文件的情况下从命令行指定一个新的数据库位置?这将使通过 Popen 调用 alembic 没什么大不了的。

  • 我看到 alembic 将其版本信息保存在一个名为 alembic_version 的简单表下,其中一列名为 version_num 并且一行指定版本。我可以在我的模式中添加一个 alembic_version 表并在创建新数据库时用最新版本填充它,这样就没有开销了吗?那是个好主意吗?我应该只使用 alembic 来创建所有数据库吗?

我的 alembic 非常适合我在项目目录中用于开发的单个数据库。我想使用 alembic 在任意位置方便地迁移和创建数据库,最好是通过某种 Python API,而不是命令行。此应用程序也被 cx_Freeze 冻结,以防有所不同。

谢谢!

原文由 John David Reaver 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 753
1 个回答

这是我在将我的软件连接到 alembic 后学到的东西:

有没有办法从我的 Python 代码中调用 alembic?

是的。在撰写本文时,alembic 的主要入口点是 alembic.config.main ,因此您可以导入它并自己调用它,例如:

 import alembic.config
alembicArgs = [
    '--raiseerr',
    'upgrade', 'head',
]
alembic.config.main(argv=alembicArgs)

请注意,alembic 在当前目录(即 os.getcwd())中查找迁移。我在调用 alembic 之前使用 os.chdir(migration_directory) 处理了这个问题,但可能有更好的解决方案。


我可以在不编辑 .ini 文件的情况下从命令行指定新的数据库位置吗?

是的。关键在于 -x 命令行参数。来自 alembic -h (令人惊讶的是,我无法在文档中找到命令行参数参考):

 optional arguments:
 -x X                  Additional arguments consumed by custom env.py
                       scripts, e.g. -x setting1=somesetting -x
                       setting2=somesetting

所以你可以创建自己的参数,例如 dbPath ,然后在 env.py 截取它:

alembic -x dbPath=/path/to/sqlite.db upgrade head

然后例如 env.py

 def run_migrations_online():
    # get the alembic section of the config file
    ini_section = config.get_section(config.config_ini_section)

    # if a database path was provided, override the one in alembic.ini
    db_path = context.get_x_argument(as_dictionary=True).get('dbPath')
    if db_path:
        ini_section['sqlalchemy.url'] = db_path

    # establish a connectable object as normal
    connectable = engine_from_config(
        ini_section,
        prefix='sqlalchemy.',
        poolclass=pool.NullPool)

    # etc

当然,您也可以在 alembic.config.main 中使用 argv 提供 -x 参数。

我同意 @davidism 关于使用迁移 vs metadata.create_all() :)

原文由 ForeverWintr 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题