我正在使用SQLite作为我的基于PySide的桌面应用程序的应用程序文件格式(请参阅here了解为什么要这样做)。也就是说,当用户使用我的应用程序时,他们的数据将保存在他们机器上的单个数据库文件中。我正在使用SQLAlchemy ORM与数据库通信。
当我发布新版本的应用程序时,我可能会修改数据库架构。我不希望用户在我每次更改架构时都必须丢弃他们的数据,所以我需要将他们的数据库迁移到最新的格式。此外,我创建了很多临时数据库来保存数据的子集以供一些外部进程使用。我想用alembic创建这些数据库,这样它们就可以用正确的版本进行标记。
我有几个问题:
- 有没有办法从Python代码内部调用alembic?我觉得在纯Python模块中使用
Popen
有点奇怪,但文档只是从命令行使用alembic。主要是,我需要将数据库位置更改为用户数据库所在的位置。 - 如果这不可能,我可以从命令行指定一个新的数据库位置,而不编辑. ini文件吗?这将使通过
Popen
调用alembic不是什么大问题。 - 我看到alembic将其版本信息保存在一个名为
alembic_version
的简单表中,该表有一列名为version_num
,还有一行指定版本,我是否可以在创建新数据库时向模式中添加一个alembic_version
表,并使用最新版本填充它,这样就没有开销了?我应该用alembic来创建所有的数据库吗?
我让alembic在我的项目目录中为我用来开发的单个数据库工作得很好。我想使用alembic在任意位置方便地迁移和创建数据库,最好是通过某种Python API,而不是命令行。这个应用程序也用cx_Freeze冻结,以防有什么不同。
谢谢!
9条答案
按热度按时间368yc8dk1#
以下是我将软件连接到
alembic
后学到的东西:有没有办法从Python代码内部调用alembic?
是的。在撰写本文时,alembic的主入口点是
alembic.config.main
,因此您可以导入它并自己调用它,例如:注意alembic在当前目录中寻找迁移(例如,os.getcwd()),我在调用alembic之前已经使用
os.chdir(migration_directory)
处理了这个问题,但是可能有一个更好的解决方案。是否可以在不编辑.ini文件的情况下从命令行指定新的数据库位置?
是的。关键在于
-x
命令行参数。从alembic -h
(令人惊讶的是,我在文档中找不到命令行参数参考):因此,您可以创建自己的参数,例如
dbPath
,然后在env.py
中截取它:alembic -x dbPath=/path/to/sqlite.db upgrade head
则例如在
env.py
中:当然,您也可以在
alembic.config.main
中使用argv
提供-x参数。我同意@davidism关于使用迁移vs
metadata.create_all()
的观点:)z4bn682m2#
如果你看一下alembic文档中的commands API页面,你会看到一个例子,说明如何直接从Python应用程序运行CLI命令,而不需要通过CLI代码。
运行
alembic.config.main
的缺点是env.py
脚本的执行可能不是你想要的。例如,它将修改你的日志配置。另一个非常简单的方法是使用上面链接的“命令API”。例如,下面是我最终编写的一个小助手函数:
我在这里使用
set_main_option
方法是为了能够在需要时在不同的DB上运行迁移。从哪里获取这两个值(路径和DSN)取决于你自己。但这似乎非常接近你想要实现的。命令API也有stamp()方法,它允许你标记一个给定的DB为特定的版本。上面的例子可以很容易地修改来调用它。
ax6ht2ek3#
这是一个非常宽泛的问题,实际上实现你的想法将取决于你,但这是可能的。
你可以从Python代码中调用Alembic,而不需要使用命令,因为它也是用Python实现的!你只需要重新创建命令在幕后所做的事情。
诚然,文档的状态不是很好,因为它们仍然是相对较早的库版本,但稍加挖掘,您将发现以下内容:
1.创建Config
1.使用配置创建ScriptDirectory
1.使用Config和ScriptDirectory创建环境上下文
1.使用环境上下文创建迁移上下文
1.大多数命令使用Config和MigrationContext中方法的某种组合
我已经编写了一个扩展来提供对Flask-SQLAlchemy数据库的这种编程式Alembic访问,该实现与Flask和Flask-SQLAlchemy绑定,但应该是一个很好的起点。
关于如何创建新数据库的最后一点,可以使用Alembic创建表,也可以先使用
metadata.create_all()
再使用alembic stamp head
(或等效的python代码),我建议始终使用迁移路径创建表,而忽略原始的metadata.create_all()
。我对cx_freeze没有任何经验,但是只要迁移包含在分发版中并且代码中指向该目录的路径正确,它就应该没问题。
4dbbbstv4#
下面是一个纯编程的示例,说明如何以编程方式配置和调用alembic命令。
目录设置(便于代码阅读)
这里是diy_alembic.py
该代码或多或少是从this Flask-Alembic file中截取的。它是查看其他命令用法和细节的好地方。
为什么选择此解决方案?-编写此解决方案时需要创建一个alembic stamp,并在运行自动化测试时进行升级和降级。
d6kp6zgx5#
我没有使用Flask,所以我不能使用已经推荐的Flask-Alembic库,相反,经过相当多的修改,我编写了下面的短函数来运行所有适用的迁移。(文件夹)名为migrations。我实际上把
alembic.ini
和env.py
放在一起,这可能有点离经叛道。下面是我的alembic.ini
文件中的一个片段,可以对此进行调整:然后,我在同一目录中添加了以下文件,并将其命名为
run.py
,但无论您将脚本保存在何处,您所需要做的只是修改以下代码以指向正确的路径:然后,有了
run.py
文件,它允许我在主代码中执行以下操作:bvuwiixz6#
参见alembic.operations.base.操作的文档:
gt0wga4j7#
对于其他任何试图用SQLAlchemy实现flyway风格的结果的人来说,这对我很有效:
将migration. py添加到项目中:
初始化数据库后,在应用程序启动时调用它
然后你只需要做剩下的标准蒸馏步骤:
将项目初始化为alembic
更新www.example.comenv.py:
更新alembic.ini
假设已经定义了SQLAlchemy模型,现在可以自动生成脚本:
如果您收到无法在www.example.com中导入模型的错误,您可以在终端中运行以下命令来修复env.py, you can run the following in your terminal fo fix
最后,我的迁移脚本是在alembic/versions目录中生成的,我必须将它们复制到migrations目录中,以便alembic提取它们。
我可能有一些配置错误,但它现在工作。
zc0qhyus8#
Alembic将其所有命令公开为
alembic.command
下的可导入调用项。https://alembic.sqlalchemy.org/en/latest/api/commands.html
我编写了这个 Package 器,这样我就可以通过python代码设置自定义日志。
x4shl7ld9#
这不是一个真正的答案,但我很难回答,所以我想分享:
如何使用alembic.command.upgrade以编程方式传递x_argument:
这里data=true是我在命令行中作为x_argument传递的值