2016-01-01 2 views
5

Я использую SQLAlchemy и MySQL с таблицей files для хранения файлов. Эта таблица определяется следующим образом:SQLAlchemy/MySQL двоичный blob кодируется utf-8?

mysql> show full columns in files; 
+---------+--------------+-----------------+------+-----+---------+-------+---------------------------------+---------+ 
| Field | Type   | Collation  | Null | Key | Default | Extra | Privileges      | Comment | 
+---------+--------------+-----------------+------+-----+---------+-------+---------------------------------+---------+ 
| id  | varchar(32) | utf8_general_ci | NO | PRI | NULL |  | select,insert,update,references |   | 
| created | datetime  | NULL   | YES |  | NULL |  | select,insert,update,references |   | 
| updated | datetime  | NULL   | YES |  | NULL |  | select,insert,update,references |   | 
| content | mediumblob | NULL   | YES |  | NULL |  | select,insert,update,references |   | 
| name | varchar(500) | utf8_general_ci | YES |  | NULL |  | select,insert,update,references |   | 
+---------+--------------+-----------------+------+-----+---------+-------+---------------------------------+---------+ 

Столбец Содержание типа MEDIUMBLOB, где хранятся файлы. В SQLAlchemy, что столбец объявлен как:

__maxsize__ = 12582912 # 12MiB                                
content = Column(LargeBinary(length=__maxsize__))       

Я не совсем уверен, о разнице между BINARY типа SQLAlchemy и LargeBinary типа. Или разница между типами MySQL VARBINARY и BLOB. И я не совсем уверен, что это имеет значение здесь.

Вопрос: Всякий раз, когда я храню фактический двоичный файл в этой таблице, то есть Python bytes или b'' объект, то я получаю следующее предупреждение

.../python3.4/site-packages/sqlalchemy/engine/default.py:451: Warning: Invalid utf8 character string: 'BCB121' 
    cursor.execute(statement, parameters) 

Я не хочу, чтобы просто игнорировать предупреждение , но кажется, что файлы находятся в такте. Как я могу обработать это предупреждение изящно, как я могу исправить его причину?

Примечание стороны:This question, кажется, связано, и это, кажется, ошибка MySQL, что он пытается преобразовать все входящие данные в UTF-8 (this answer).

+0

Вы, кажется, используете Python. Две «Боковые заметки» относятся к проблемам PHP и Perl. Что-то в _Python_ не выполняет ваш запрос на использование данных «blob». –

+0

@RickJames: Да, все Python. Ссылка «[этот ответ] (http://stackoverflow.com/questions/14734812/is-a-blob-converted-using-the-current-default-charset-in-mysql#14745685)» в боковой заметке, однако, похоже, это проблема MySQL. Если это проблема Python, я бы все же хотел понять, что мне здесь не хватает ... – Jens

+0

Если _client_ (PHP, Python и т. Д.) Обрабатывает строку как «символы», тогда эта проблема может возникнуть. Если рассматривать его как произвольные «байты», то проблема не возникает. Хранение в MySQL 'BLOB' не делает проверку utf8; сохранение в 'TEXT' делает. –

ответ

0

Оказывается, это была проблема с драйвером. По-видимому, драйвер MySQL по умолчанию сталкивается с поддержкой Py3 и utf8. Установка cymysql в виртуальную среду Python разрешила эту проблему, и предупреждения исчезли.

Исправление: Узнайте, подключается ли MySQL через сокет или порт (см. here), а затем соответствующим образом изменяйте строку подключения. В моем случае, используя сокет:

mysql+cymysql://user:[email protected]/database?unix_socket=/var/run/mysqld/mysqld.sock 

Используйте port аргумент иначе.

Редактировать: В то время как вышеописанная проблема с кодировкой, она породила еще одну: размер блоба. Из-за a bug in CyMySQL blobs больше 8M не могут зафиксировать. Переключение на PyMySQL исправлено, что проблема, хотя кажется, имеет similar issue с большими каплями.

+0

Фактически, это, по-видимому, сервер MySQL, который генерирует это предупреждение, а способ вокруг него - использовать '_binary', чтобы сказать, что вещь, которую вы вставляете, не должна интерпретироваться. См. Https://bugs.mysql.com/bug.php?id=79317 – Wodin

0

Не уверен, но ваша проблема может иметь те же корни, что и у меня несколько лет назад в python 2.7: https://stackoverflow.com/a/9535736/68998. Короче говоря, интерфейс Mysql не позволяет вам быть уверенным в том, что вы работаете с истинной двоичной строкой или текстом в двоичной сортировке (используется из-за отсутствия сортировки utf8 с учетом регистра). Таким образом, связывание Mysql имеет следующие параметры:

  • вернуть все строковые поля в виде двоичных строк, и оставьте расшифровку вам
  • расшифровывает только те поля, которые не имеют двоичный флаг (так весело, когда некоторые поля являются unicode и другие являются str)
  • имеют возможность заставить декодирование unicode для всех строковых полей, даже верно бинарное

Я думаю, что в вашем случае, третий вариант где-то включен я n лежащая в основе привязка Mysql. И первым подозреваемым является ваша строка соединения (параметры подключения).

+0

Моя текущая строка подключения: 'mysql: // user @ localhost/database? Charset = utf8'. В соответствии с [документацией] (https://dev.mysql.com/doc/connector-net/en/connector-net-connection-options.html) параметр «charset» «Определяет набор символов, который должен использоваться для кодировать все запросы, отправленные на сервер. «Запросы Hmm-encode * all *? – Jens

Смежные вопросы