python sqlalchemy alembic

python - ¿Es posible almacenar la cadena de conexión de alambique fuera de alembic.ini?



alembic python (5)

Estoy usando Alambique con SQL Alchemy. Con SQL Alchemy, tiendo a seguir un patrón donde no almaceno la cadena de conexión con el código versionado. En cambio, tengo el archivo secret.py que contiene información confidencial. .gitignore este nombre de archivo en mi .gitignore para que no termine en GitHub.

Este patrón funciona bien, pero ahora estoy usando Alembic para migraciones. Parece que no puedo ocultar la cadena de conexión. En cambio, en alembic.ini, coloca la cadena de conexión como un parámetro de configuración :

# the ''revision'' command, regardless of autogenerate # revision_environment = false sqlalchemy.url = driver://user:pass@localhost/dbname # Logging configuration [loggers] keys = root,sqlalchemy,alembi

Me temo que voy a cometer accidentalmente un archivo con información de nombre de usuario / contraseña para mi base de datos. Prefiero almacenar esta cadena de conexión en un solo lugar y evitar el riesgo de comprometerla accidentalmente con el control de la versión.

¿Que opciones tengo?


Entonces, lo que parece funcionar es la reimplementación de la creación del motor en env.py, que aparentemente es un lugar para hacer este tipo de personalización. En lugar de usar la cadena sqlalchemy connect en el ini:

engine = engine_from_config( config.get_section(config.config_ini_section), prefix=''sqlalchemy.'', poolclass=pool.NullPool)

Puede reemplazar y especificar su propia configuración de motor:

import store engine = store.engine

De hecho, los documentos parecen implicar que esto está bien:

sqlalchemy.url: una URL para conectarse a la base de datos a través de SQLAlchemy. De hecho, esta clave solo se referencia en el archivo env.py que es específico de la configuración "genérica"; un archivo que puede ser personalizado por el desarrollador. Una configuración de base de datos múltiple puede responder a varias claves aquí, o puede hacer referencia a otras secciones del archivo.


Otra solución es crear una plantilla de archivo alembic.ini.dist y rastrearla con su código versionado, ignorando a alembic.ini en su VCS.

No agregue ninguna información confidencial en alembic.ini.dist:

sqlalchemy.url = ...

Al implementar su código en una plataforma, copie alembic.ini.dist a alembic.ini (este no será rastreado por su VCS) y modifique alembic.ini con las credenciales de la plataforma.


Ayer tuve el mismo problema y encontré una solución para trabajar. Hago lo siguiente en env.py :

# this is the Alembic Config object, which provides # access to the values within the .ini file in use. config = context.config # this will overwrite the ini-file sqlalchemy.url path # with the path given in the config of the main code import config as ems_config config.set_main_option(''sqlalchemy.url'', ems_config.config.get(''sql'', ''database''))

ems_config es un módulo externo que contiene mis datos de configuración.

config.set_main_option(...) esencialmente sobrescribe la clave sqlalchemy.url en la sección [alembic] del archivo alembic.ini . En mi configuración simplemente lo dejo negro.


La documentación de Alembic sugiere el uso de create_engine con la URL de la base de datos (en lugar de modificar sqlalchemy.url en el código ).

También debe modificar run_migrations_offline para usar la nueva URL. Allan Simon tiene un ejemplo en su blog, pero en resumen, modifique env.py para:

  1. Proporcione una función compartida para obtener la URL de alguna manera (aquí viene de la línea de comando):

    def get_url(): url = context.get_x_argument(as_dictionary=True).get(''url'') assert url, "Database URL must be specified on command line with -x url=<DB_URL>" return url

  2. Use la URL en modo fuera de línea:

    def run_migrations_offline(): ... url = get_url() context.configure( url=url, target_metadata=target_metadata, literal_binds=True) ...

  3. Use la URL en el modo en línea usando create_engine lugar de engine_from_config :

    def run_migrations_online(): ... connectable = create_engine(get_url()) with connectable.connect() as connection: ...


Como Doug T. dijo , puede editar env.py para proporcionar URL desde otro lugar que no sea el archivo ini. En lugar de crear un motor nuevo, puede pasar un argumento url adicional a la función engine_from_config (los kwargs se fusionan más tarde con opciones tomadas del archivo ini). En ese caso, podría, por ejemplo, almacenar la contraseña cifrada en un archivo ini y descifrarla en tiempo de ejecución mediante frase de contraseña almacenada en la variable ENV.

connectable = engine_from_config( config.get_section(config.config_ini_section), prefix=''sqlalchemy.'', poolclass=pool.NullPool, url=some_decrypted_endpoint)