2016-01-01 27 views
5

私はファイルを格納するfilesテーブルとSQLAlchemyとMySQLを使用しています。ファイルが格納されている場所のタイプMEDIUMBLOBSQLAlchemy/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 |   | 
+---------+--------------+-----------------+------+-----+---------+-------+---------------------------------+---------+ 

コンテンツ列は次のようにそのテーブルが定義されています。私はSQLAlchemyののBINARYタイプとLargeBinaryタイプの違いについてかなりわからない

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

:SQLAlchemyのでは、その列は次のように宣言されています。または、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関連しているように思われ、UTF-8(this answer)にすべて入ってくるデータを変換しようとすると、MySQLのバグのようです。

+0

あなたはPythonを実行しているようです。 2つの「サイドノート」は、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引数を使用します。私の場合、ソケット接続を使用して。

編集:上記のコードではエンコードの問題が修正されましたが、もう1つはブロブサイズになりました。 a bug in CyMySQLのBLOBが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。簡単に言えば、真のバイナリ文字列やバイナリ照合のテキスト(大文字小文字を区別するutf8照合の欠如のために使用される)で作業している場合、Mysqlのインターフェイスはあなたに確信させません。いくつかの(とても楽しいバイナリフラグを持っていないフィールドだけデコードを

  • リターンバイナリ文字列など、すべての文字列フィールドを、そして
  • あなたにデコードを残す:したがって、結合MySQLは、以下のオプションがありますフィールドのunicode、他方がstrある)
  • は、すべての文字列フィールドにunicodeに復号を強制するためのオプションを持っています、でも本当のバイナリ

私の推測では、あなたのケースでは、第3のオプションはどこかに私が有効になっていることですn基になるMysqlバインディング最初の容疑者は接続文字列(接続パラメータ)です。

+0

私の現在の接続文字列は 'mysql:// user @ localhost/database?charset = utf8'です。 [documentation](https://dev.mysql.com/doc/connector-net/en/connector-net-connection-options.html)によれば、 'charset'オプションは、"使用すべき文字セットを指定しますサーバーに送信されたすべてのクエリをエンコードします。 "Hmm-encode * all *クエリ? – Jens

関連する問題