【问题标题】:Python - Packaging Alembic Migrations with SetuptoolsPython - 使用 Setuptools 打包 Alembic 迁移
【发布时间】:2017-07-12 00:35:48
【问题描述】:

将 Alembic 迁移文件打包到 Setuptools setup.py 文件中的正确方法是什么?一切都在我的回购根目录中,为alembic/

这是一个 Python 应用程序,而不是一个库。

我想要的安装流程是有人可以pip install 我的应用程序的轮子。然后他们可以通过运行<app> alembic upgrade --sqlalchemy.url=<db_url> 之类的东西来初始化应用程序数据库。然后升级需要pip install -U,之后他们可以再次运行 Alembic 命令。

这是非正统吗?

如果没有,我将如何实现?当然是console_scriptsentry_points。但除此之外呢?

【问题讨论】:

    标签: python setuptools alembic


    【解决方案1】:

    我不确定这是不是正确的方法,但我是这样做的:

    首先,您可以使用 -x 选项向 alembic 添加一些自定义选项,您可以在this great answer 中找到详细说明。这允许您在运行时指定db_url 并使其覆盖config.ini 中的值。

    然后,我通过将alembic.ini 文件和alembic 目录从我的项目根目录移动到我的顶级python 包,成功地打包了alembic 和我的迁移:

    <project root>
    ├── src
    │   └── <top-level package dir>
    │       ├── alembic
    │       │   ├── env.py
    │       │   ├── README
    │       │   ├── script.py.mako
    │       │   └── versions
    │       │       ├── 58c8dcd5fbdc_revision_1.py
    │       │       └── ec385b47da23_revision_2.py
    │       ├── alembic.ini
    │       ├── __init__.py
    │       └── <other files and dirs>
    └── <other files and dirs>
    

    这允许在我的setup.py 中使用 setuptools package_data 指令:

    setup(
        name=<package_name>,
        package_dir={'': 'src'},
        packages=find_packages(where='src'),
        package_data={
            '<top-level package dir>': ['alembic.ini', 'alembic/*', 'alembic/**/*'],
        },
        [...]
    )  
    

    此时,alembic 配置和修订已正确打包,但必须调整 alembic.ini 设置以反映新目录树。可以使用%(here)s 参数来完成,该参数包含包含alembic.ini 文件的目录的绝对路径:

    # A generic, single database configuration.
    
    [alembic]
    # path to migration scripts
    script_location = %(here)s/alembic
    
    [...]
    
    # version location specification; this defaults
    # to alembic/versions.  When using multiple version
    # directories, initial revisions must be specified with --version-path
    # version_locations = %(here)s/bar %(here)s/bat alembic/versions
    version_locations = %(here)s/alembic/versions
    
    [...]
    

    最后,您必须使用允许提供配置文件路径的-c 选项调用alembic

    alembic -c <path to alembic.ini> ...
    

    【讨论】:

    • 谢谢!我想知道是否有办法让 setuptools 'package''package_data'kwargs 使用 Java/Maven 样式的目录结构,即 ./src/main/python/./src/main/db/
    【解决方案2】:

    将主alembic 文件夹保留在主包文件夹中的一种方法是将alembic 文件夹视为要与主包一起安装的自己的包。

    为此,您必须重命名它(它不能称为alembic,因为它将是一个顶级包,所以需要一个唯一的名称 - 我用过migrations),并添加一个@987654323 @alembic 文件夹和版本文件夹中的文件。

    在部署时运行迁移需要知道已安装包的路径 - 一种简单的方法是提供应用迁移的控制台脚本。

    所以项目结构如下:

    <project root>
    ├── setup.py
    ├── mypackage
    │   └── <project source files...>
    │
    ├── migrations
    │   ├── __init__.py
    │   ├── alembic.ini
    │   ├── apply.py
    │   ├── env.py
    │   ├── README
    │   ├── script.py.mako
    │   └── versions
    │       ├── __init__.py
    │       ├── 58c8dcd5fbdc_revision_1.py
    │       └── ec385b47da23_revision_2.py
    │
    └── <other files and dirs>
    

    还有setup.py

    from setuptools import find_packages
    from setuptools import setup
    
    
    setup(
        name='mypackage',
        packages=find_packages(exclude=('tests',)),
        package_data={'migrations': ['alembic.ini']},
        entry_points={
            'console_scripts': ['apply-migrations=migrations.apply:main'],
        },
        install_requires=[
            "SQLAlchemy==1.3.0",
            "alembic==1.0.10",
            # ...
        ]
    )
    

    最后是migrations/apply.py:

    # Python script that will apply the migrations up to head
    import alembic.config
    import os
    
    here = os.path.dirname(os.path.abspath(__file__))
    
    alembic_args = [
        '-c', os.path.join(here, 'alembic.ini'),
        'upgrade', 'head'
    ]
    
    
    def main():
        alembic.config.main(argv=alembic_args)
    

    现在安装轮子后,您将拥有一个可以直接调用的命令apply-migrations。请注意,我在这里实现的版本没有任何参数 - 尽管如果你想通过例如。 --sqlalchemy.url 可以添加到alembic_args

    我个人更喜欢将网址设置为migrations/env.py。例如,如果您有一个名为 SQLACLHEMYURL 的环境变量,您可以将其添加到 migrations/env.py

    import os
    config.set_main_options(os.getenv('SQLALCHEMYURL'))
    

    然后你可以调用:

    SQLALCHEMYURL=... apply-migrations
    

    在部署中。

    【讨论】:

    • 这个包名是migrations,包名应该是mypackage.migrationsentry_point应该是'apply-migrations=mypackage.migrations:main'
    • 在另一个包中安装轮子后,我运行了apply-migrations 命令,我得到了FAILED: Path doesn't exist: Please use the 'init' command to create a new scripts folder. 之类的异常,我们需要在alembic.ini 文件中放入什么script_location?
    猜你喜欢
    • 2013-07-04
    • 2012-06-26
    • 2016-12-25
    • 2014-12-02
    • 1970-01-01
    • 2017-05-12
    • 2013-03-17
    • 2014-05-18
    • 2020-04-20
    相关资源
    最近更新 更多