Я потратил на это более 3 часов в течение 18 из 21 дня. Пожалуйста, кто-нибудь, скажите мне, что я неправильно понимаю!
TL; DR: Мой код многократно отправляет набор символов db в виде строки в PyMysql, в то время как он ожидает объект с атрибутом, называемым "encoding"
Фон
Это код Python, выполняемый в контейнере Docker. Второй контейнер содержит базу данных. Адрес базы данных хранится в переменной .env
с именем ENGINE_URL
:
ENGINE_URL=mysql+pymysql://root:@database/starfinder_development?charset=utf8
Я запускаю команды Alembic и Flask-Alembic, используя команды click
в CLI. Все перечисленные ниже методы используются в командах CLI.
Модели / Настройка базы данных (работает)
from flask import Flask
flask_app = Flask(__name__)
db_engine = SQLAlchemy(flask_app)
from my_application import models
def create_database():
db_engine.create_all()
Теперь я могу открыть контейнер базы данных и использовать CLI MySql, чтобы увидеть, что все мои модели теперь преобразованы в таблицы со столбцами и связями.
Попытка 1: Alembic
Создание файлов ревизий с помощью Alembic (работает)
from alembic.config import Config
def main(): # fires prior to any CLI command
filepath = os.path.join(os.path.dirname(__file__),
"alembic.ini")
alembic_config = Config(file_=filepath)
alembic_config.set_main_option("sqlalchemy.url",
ENGINE_URL)
alembic_config.set_main_option("script_location",
SCRIPT_LOCATION)
migrate_cli(obj={"alembic_config": alembic_config})
def revision(ctx, message):
alembic_config = ctx.obj["alembic_config"]
alembic_command.revision(alembic_config, message)
На данный момент у меня есть файл миграции, который был создан точно так, как ожидалось. Затем мне нужно обновить базу данных, используя эту миграцию ...
Запуск миграций с Alembic (не удается)
def upgrade(ctx, migration_revision):
alembic_config = ctx.obj["alembic_config"]
migration_revision = migration_revision.lower()
_dispatch_alembic_cmd(alembic_config, "upgrade",
revision=migration_revision)
запуск этого с cli_command upgrade head
вызывает сбой, который я включил здесь внизу, потому что он имеет трассировку стека, идентичную моей второй попытке.
Попытка 2: колба-алембик
Эта попытка обнаруживает, что я полностью переписываю свои команды main
и revision
, но это не так далеко, как использование upgrade
.
Создание файлов редакции с помощью Flask-Alembic (ошибка)
def main(): # fires prior to any CLI command
alembic_config = Alembic()
alembic_config.init_app(flask_app)
migrate_cli(obj={"alembic_config": alembic_config})
def revision(ctx, message):
with flask_app.app_context():
alembic_config = ctx.obj["alembic_config"]
print(alembic_config.revision(message))
Это приводит к ошибке, идентичной ошибке из моей предыдущей попытки.
Трассировка стека в обоих случаях:
(Идентичный сбой при обновлении alembic и ревизии склянки-alembic)
File "/Users/MyUser/.pyenv/versions/3.6.2/envs/sf/lib/python3.6/site-packages/pymysql/connections.py", line 678, in __init__
self.encoding = charset_by_name(self.charset).encoding
AttributeError: 'NoneType' object has no attribute 'encoding'
В ответ я зашел в вышеуказанный файл и добавил печать на L677
, непосредственно перед ошибкой:
печать (self.charset)
utf8
Примечание: Если я изменю свой ENGINE_URL
, чтобы использовать другой ?charset=xxx
, это изменение будет отражено здесь.
Так что теперь я в тупике
PyMysql ожидает, что self.charset
будет иметь атрибут encoding
, но self.charset
- это просто строка. Как я могу изменить это, чтобы вести себя как ожидалось?
Помощь
Правильный ответ будет альтернативным процессом, хотя "самый правильный" ответ будет помочь мне решить проблему с кодировкой / кодировкой.
Моя основная задача здесь - просто запустить миграцию в моем приложении для колб.