一つ前の「Flask で始める Google AppEngine アプリ開発」の番外編です。
前回は Flask + Appengine という観点でアプリ開発を始め方について説明しましたが、
番外編ではアプリ移植の際に手間をかけたデータ移行について説明します。
今回移植した GMappers というアプリは元々 MySQL 上にデータを保存していたため、
Appengine に移植するにあたりデータを移行する必要がありました。
いろいろ調べてみたところ、Appengine では bulkloader.py を用いてデータ移行をする方法が
よく知られているようです。
しかし、bulkloader.py は CSV をインポートするという仕組みであるため、
MySQL → CSV → Appengine というステップを踏む必要があります。
つまり、今回のケースでは
- MySQL から CSV を抽出するプログラム
- CSV をモデル化して Appengine に登録するプログラム
が必要になります。
また、この方法では ReferenceProperty を使って他のデータを参照するのは難しいようです。
もう少しデータ移行について調べていったところ Appengine の提供する
remote_api というライブラリがこの問題を解決できることに気づきました。
remote_api を利用することで、ローカル環境から Appengine 環境のデータを操作することができます。
※ remote_api は remote_api_shell コマンドなどで利用されています。
というわけで、remote_api を利用して開発したのが gaerunner というツールです。
gaerunner は指定したプログラムを Appengine 環境につないで実行することができます。
これを利用すると
- ローカルの DB から Appengine へデータ移行する
- Appengine からローカルの DB にデータを抜き出す
- Appengine 上のデータを他のモデルに変換する (データ移行する)
などの処理を簡単に実現することができます。
gaerunner を使うには
- gaerunner をインストールする (easy_install gaerunner)
- appengine アプリケーションで remote_api の使用を許可する (app.yaml 内で指定する)
という手順を踏む必要があります。
前回の記事の buildout.cfg にはこの手順を含んでいるため、
ここではセットアップについては割愛します。
前回の記事を読んで環境を構築するか、自分で調べて環境を作ってみて下さい。
では、早速 MySQL から Appengine へのデータ移行スクリプトを準備します。
import _mysqlfrom google.appengine.ext import dbclass Map(db.Model):map_id = db.IntegerProperty(required=True)name = db.StringProperty(required=True)description = db.TextProperty()cn = _mysql.connect(host, user, passwd, db)cn.query('SELECT * FROM maps')map_rs = cn.store_result()for i in range(map_rs.num_rows()):r = map_rs.fetch_row()[0]map = Map(map_id=int(r[0]),name=unicode(r[1], 'utf-8'),description=unicode(r[2], 'utf-8'))map.put()
このスクリプトでは、MySQL の maps テーブルからレコードを取り出し
各レコードを Map モデルとして保存(put)しています。
このスクリプトを gaerunner を使って次のように実行します。
% bin/gaerunner gmappers import_from_mysql.py※ gmappers の部分はアプリケーション ID を指定して下さい
上記を実行すると gaerunner は remote_api を経由して
Map データを Appengine 環境に保存します。
これにより MySQL から Appengine へのデータ移行が実現されます。


[gaerunner]セクションは作らずに[debug]セクションのeggsにtk0.gaerunnerを追加しても良かったかも知れませんね。
tk0.gaerunnerとローカルDB・DataStore直接接続はすごい。まねします。