SQLAlchemyを利用してPandasのデータをMySQLに保存するときハマったよ

pandasのDataFrameをできるだけコードを書かずにDBに登録できないか調べたところ
sqlalchemyというライブラリがあったので試しました。
ところがデータベースのパスワードに特殊記号+&(などが含まれた場合、接続に失敗します。
このパスワードをエンコードする必要がありました。。。
わかるまで、時間を浪費してしまったので、共有します。

公式ドキュメント
公式には
the string format of the URL is an RFC-1738-style string.
とあり、データベースに接続するためのURLをRFC-1738の形式にしてねと書いてありました。

test用データベースの作成

# とりあえずtest用データベースの作成
sqlalchemyの検証用データベースを作成する。(mysqlにログインしてSQLを実行)
検証後にわかったのですが、メソッドto_sqlの引数にif_exists=’append’とすると新規にテーブルが作成される。

CREATE TABLE IF NOT EXISTS `mytest` (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `name` varchar(12) NOT NULL,
    `age` int(11) DEFAULT '0',
    `phone` varchar(13) DEFAULT '',
    PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

必要なライブラリをインストールする

前提としてpandasはインストール済み。
MySQLの接続にはPyMySQLを使います。(他のライブラリのある方はそのまま使えるらしい)

# install

pip install PyMySQL
pip install SQLAlchemy

テストサンプルコード

標準ライブラリurllib.parseを使用
# Test code

15行目でquote_plusしてpasswordをencodeする。

import pandas as pd
import urllib.parse as ps
import sqlalchemy as sa

df = pd.DataFrame({"name":["taro", "hanako", "jiro"],
                   "age":[12, 18, 21],
                   "phone":['090-0000-0000', '090-1111-2222', '090-3333-4444']})

# ここではrootを使って説明してますが、実装は必ずdb用のユーザーを作成して、
# そのユーザーへDBの操作権限をGRANTしてください。パスワードとかDBユーザは各自のもので読み替えてください。
# 特殊記号が含まれなければquote_plusする必要はない。
password = '&5kM4eq('

# the string format of the URL is an RFC-1738-style string.
# 特殊記号の入ったパスワードをencodeする
con_url = 'mysql+pymysql://root:{}@localhost/test_db?charset=utf8'.format(ps.quote_plus(password))

# 第二引数をecho=Trueにすれば、何をやっているか内部の処理がわかります
engine = sa.create_engine(con_url, echo=False)
df.to_sql('myest', engine, index=False, if_exists='replace')

引数if_exists=’replace’とすると、テーブルをDFの内容に沿って既存テーブルがあってもドロップし再作成するようです。
ちょっと使用上困るかも。
これだと一時的な作業テーブルとして扱わないと厳しい。
if_exits=’append’とすれば、あらかじめテーブルは作成する必要はない。あらかじめ準備した既存テーブルへデータが追加されます。

今日は以上です。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です