レベル: 中級 Michael Galpin, Developer, eBay
2008年 8月 05日 ソーシャル・ソフトウェアを活用することは、アプリケーションに価値を加える素晴らしい手段となり得ます。ソーシャル・ネットワークでは、画期的な新しい Web アプリケーションを作成するためのデータを容易に収集してマッシュアップできるからです。しかしそれでもやはり、スケーラブルな Web アプリケーションを作成する上で常に伴う問題のすべては、自分で処理しなければなりません。この部分の負担を軽くしてくれるのが、GAE (Google App Engine) です。GAE を使用すれば、アプリケーション・サーバーのプールの管理について一切忘れ、大量の静的コンテンツと動的データの保存について懸念することなく優れたマッシュアップを作成することに専念できます。この 3 回連載の「Google App Engine をベースに Eclipse を使用して作成するマッシュアップ」の第 1 回では、GAE アプリケーションの開発に取り掛かる方法を説明し、GAE 開発をさらに容易にするために、どのように Eclipse を利用するかを検討します。
この連載について
この連載では、GAE (Google App Engine) を使い始める方法を紹介します。この第 1 回でまず焦点とするのは、GAE で実行するアプリケーションの作成を開始できるように開発環境をセットアップすることです。その後、Eclipse を利用してアプリケーションの開発とデバッグを容易にする方法を説明します。第 2 回では、Eclipse を使って Ajax マッシュアップを構築し、そのマッシュアップを GAE にデプロイします。そして最終回の第 3 回目で、アプリケーションに RESTful なサービスを作成することによってエコシステムに還元し、他の開発者もこのアプリケーションを使ってそれぞれ独自のマッシュアップを作成できるようにします。
GAE は、Web アプリケーションを作成するためのプラットフォームです。GAE で使用するのは Python (現在のバージョンは、Python V2.5.2) であることから、GAE を使うにはこのプログラミング言語についての知識があることが最大の前提条件となります。この連載を読むにあたっては、ある程度の一般的な Web 開発スキル (HTML、JavaScript、CSS の知識) があると役立ちます。GAE 対応の開発を行うには、以下の 3 つのソフトウェア・パッケージをダウンロードする必要があります。
- Eclipse Classic
- この連載では Eclipse Classic V3.3.2 を使用しました。これ以降のバージョンでも有効です。
- Google App Engine SDK
- GAE サイトに、公式ドキュメントと SDK のダウンロード・リンクが用意されています。
- PyDev
- Eclipse を Python IDE に変身させる PyDev は、Eclipse 内で更新サイト (http://pydev.sourceforge.net/updates/) を指定してインストールすることができます。
最後の 2 つのソフトウェア・パッケージをインストールする方法については、この後詳しく説明します。Eclipse を使用するのが初めての方は、まずは「参考文献」を参照してください。
GAE のセットアップ方法
ある程度の Web アプリケーションの開発経験があれば、新しいアプリケーション・スタックに取り掛かる際にライブラリー、Web サーバー、データベースをダウンロードする作業には慣れていることでしょう。場合によっては、これらの作業のすべてをインストーラーにバンドルし、ファイルを適切に配置し直すといった作業を多少なりとも簡単にできるようになっていることもあります。通常はすべてを所定の位置に配置した後、お気に入りの開発環境で操作できるようにするための厄介な作業をさらに行わなければなりませんが、GAE を使う場合にはその限りではありません。早速、GAE をセットアップする方法、そして Eclipse と連動させる方法を見ていくことにしましょう。
GAE をセットアップするために最初に必要な作業は、SDK をダウンロードすることです。SDK には Microsoft® Windows® 用、Mac OS X 用、Linux® 用があり、Windows 用と Mac OS X用の SDK はインストーラーとして提供されます。このインストーラーはシステムに SDK をインストールするだけでなく、いくつかの重要な実行可能スクリプトもすぐに使えるようにあらかじめパスに配置してくれます。SDK のディレクトリー構造は、図 1 に示すようになります。
図 1. GAE SDK ディレクトリー構造
ディレクトリーのルートを見ると、2 つの Python スクリプト、appcfg.py と dev_appserver.py があります。dev_appserver.py は、開発アプリケーション・サーバーを起動するために使用するスクリプトです。アプリケーションの開発およびテストに個別のインストール、デプロイメントは必要ありません。もう一方の appcfg.py スクリプトは、アプリケーションを GAE にデプロイする準備が整ったときに使用します。
Google ディレクトリーには GAE プラットフォームの基礎となるすべての API があり、必然的に、このディレクトリーにあるクラスを使用および継承することになります。したがって、何かから GAE アプリケーション・コードを実行する場合には、このディレクトリーについて把握している必要があります。GAE アプリケーション・コードを実行するには、そのコードが使用する API を把握していなければならないからです。その一例として、GAE コードを開発するための Eclipse をセットアップする方法を説明します。
Eclipse のセットアップ方法
Eclipse は、Java™ プログラミング言語のアプリケーションを開発する際の代表的な IDE として知られています。しかし、Eclipse は Java 開発者だけのものではありません。C++、PHP、Ruby、そして Python など、他の多くの言語にも使用されています。実際、Eclipse を Python IDE に変換する Eclipse プラグインはいくつも用意されています。なかでも最もよく使用されているのは、PyDev です。PyDev は Eclipse の更新サイト (http://pydev.sourceforge.net/updates/) からインストールすることができます。
PyDev をインストールしたら、今度は PyDev を構成する必要があります。Eclipse を開いて、Preferences > PyDev に進んでください。
図 2. PyDev の構成
PyDev には Python のインストール場所を指定する必要があるので、上記のように Interpreter > Python の順に進んで New をクリックします。Python V2.5+ インストールまでナビゲートするだけで、後の作業は Eclipse が行ってくれます。OK をクリックすれば、Eclipse で Python を開発できるようになります。
アプリケーションを作成する
まずは、Eclipse で新しい PyDev を作成するところから始めます。それには、Windows > Open Perspective > Other を選択し、使用可能なパースペクティブのリストから PyDev を選んで PyDev パースペクティブに切り替えます。
図 3. PyDev パースペクティブの表示
これで、File > New > PyDev Project を選択すれば、新規アプリケーションの作成に取り掛かれます。この例ではソース・コード用に別個の src フォルダーを作成することにしますが、これはオプションで、ほとんど好みの問題です。今まで行ってきた作業はすべて Eclipse での Python 開発に一般的なことでしたが、ここからは GAE 特有の作業に入ります。
GAE テンプレート・プロジェクト
GAE プロジェクトはレイアウトの点では単純で、ディレクトリーは 1 つしかなく、サブディレクトリーはありません。必要なファイルは、app.yaml、index.yaml、main.py の 3 つです。このうち、最初の app.yaml ファイルを以下に記載します。
リスト 1. app.yaml
application: aggrogator
version: 1
runtime: python
api_version: 1
handlers:
- url: .*
script: main.py
|
これは、GAE アプリケーションの主要な構成ファイルです。このファイルに含まれるほとんどの項目は 1 度設定すればよいだけで、例えばアプリケーションの名前、バージョン、そしてアプリケーションの作成に使用した GAE API のバージョンなどがこれに該当します。それよりも作業量が多くなる部分は handlers のセクションです。handlers セクションでは HTTP リクエストの URL とプロジェクト内の Pythonスクリプトを対応付けます。上記の例では、すべての HTTP リクエストの URL が同じ 1 つの main.py スクリプトにマッピングされています。この main.py ファイルでさらにルーティングを行って、URL をメソッドに一致させることができます。
もう 1 つの YAML ファイル、index.yaml は GAE がデータを効率的にフェッチできるようにするためのファイルです。実際のところ、このファイルがなくても支障はありません。ファイルが用意されていなければ、GAE が自動的に生成するからです。今のところ、このファイルで必要な作業は何もないので、リスト 2 にはブランク状態のファイルを記載します。
リスト 2. index.yaml
indexes:
# AUTOGENERATED
# This index.yaml is automatically updated whenever the dev_appserver
# detects that a new type of query is run. If you want to manage the
# index.yaml file manually, remove the above marker line (the line
# saying "# AUTOGENERATED"). If you want to manage some indexes
# manually, move them above the marker line. The index.yaml file is
# automatically uploaded to the admin console when you next deploy
# your application using appcfg.py.
|
いよいよ、アプリケーションの核心部分、main.py スクリプトです。app.yaml の内容と矛盾しない限り、このファイルにはどんな名前を付けても構いません。一般的に使用される名前は main.py なので、ここではこの名前を使用します。このファイルを検討する前に、これから作成するアプリケーションのタイプについて説明しておきます。
aggroGator
このサンプル・アプリケーションの名前は、aggroGator です。このアプリケーションでは、ユーザーがすでに使用している各種の Web サービスにユーザー自身を関連付けることができます。すると、アプリケーションはこれらのサービスからデータ・フィードを取得して、時系列で集約します。このアプリケーションでフィードの構文解析に使用するのは、評判の高い FeedParser ライブラリーです。さらに、Google を介して GAE の組み込み ID 管理機能を使用するため、独自の登録/ログイン/ログアウト機能を作成する必要はありません。ユーザーは単純に Google ID を使ってログインします。これらの点を念頭に、main.py を見てみましょう。
リスト 3. main.py
def main():
application = webapp.WSGIApplication(
[('/', MainPage),
('/add', AddService)],
debug=True)
wsgiref.handlers.CGIHandler().run(application)
if __name__ == "__main__":
main()
|
見てのとおり、これは単なるスクリプトの main メソッドに過ぎません。このスクリプトが実行することは、追加のルーティングをセットアップするだけです。この例では、「/」に対するリクエストの場合は MainPage というクラスにルーティングし、「/add」に対するリクエストの場合は AddServiceというクラスにルーティングします。以下に、MainPage クラスを記載します。
リスト 4. MainPage
class MainPage(webapp.RequestHandler):
def get(self):
user = users.get_current_user()
if users.get_current_user():
url = users.create_logout_url(self.request.uri)
url_linktext = 'Logout'
else:
url = users.create_login_url(self.request.uri)
url_linktext = 'Login'
updates = []
account = None
if user:
account_query = Account.all()
account_query.filter('user = ', users.get_current_user())
result_set = account_query.fetch(1)
if len(result_set) > 0:
account = account_query.fetch(1)[0]
if account:
updates = []
for service in account.dynamic_properties():
url = getattr(account, service)
feed = GenericFeed(url, service)
updates.extend(feed.entries())
else:
account = Account()
account.user = user
account.put()
updates.sort(key=attrgetter('timestamp'), reverse=True)
template_values = {
'account': account,
'updates': updates,
'url': url,
'url_linktext': url_linktext,
}
path = os.path.join(os.path.dirname(__file__), 'index.html')
self.response.out.write(template.render(path, template_values))
|
このクラスはアプリケーションのメイン・コントローラーであるため、その実行内容は盛りだくさんです。まず注目する点として、このクラスには get メソッドしかありません。つまり、このクラスがサポートするのは HTTP GET リクエストのみで、[/」に対する POST はエラーになります。次にこのクラスが行うのは、ID のチェックです。users クラスは GAE SDK の API で、この API では Google の ID 管理機能を利用します。ここでは、この機能を使用してユーザーがログインしているかどうかをチェックするため、ユーザーがログインしている場合には、そのユーザーが誰であるのか (つまり、そのユーザーの Google ID) がわかるというわけです。続いて、ユーザーがログインしているかどうかに応じて、ログインまたはログアウト・リンクを作成します。ユーザーがログインしていなければ単にログイン・リンクを表示し、ログインしていれば、アカウントを参照して処理を続けます。Account クラスは、このアプリケーションのために作成したもう 1 つのクラスです。以下を参照してください。
リスト 5. TheAccount クラス
class Account(db.Expando):
user = db.UserProperty()
|
このクラスが利用するのは Google のデータ・ストレージ API (Google の有名な Bigtable データ・ストア) です。Account エンティティーは User プロパティーを持ち、Expando モデルとなっています。そのため、動的プロパティーの作成、つまり各サービスの URL ごとにプロパティーを作成することができます。サービスごとのエントリーのリストを取得するには、以下に示す GenericFeed クラスを使用します。
リスト 6. GenericFeed クラス
class GenericFeed:
def __init__(self, url, name):
self.url = url
self.name = name
def entries(self):
result = urlfetch.fetch(self.url)
updates = []
if result.status_code == 200:
feed = feedparser.parse(result.content)
for entry in feed['entries']:
x = Entry()
x.service = self.name
x.title = entry['title']
x.link = entry['link']
if entry.summary:
x.content = entry.summary
else:
x.content = entry['title']
x.timestamp = entry.updated_parsed
updates.append(x)
return updates
|
これが、FeedParser ライブラリーを使用するクラスです。このライブラリーを使用する前には、GAE API の別のクラス、urlfetch を使用します。このクラスは HTTP リクエストを許容しますが、ただし、ポート 80 および 443 (セキュアなリクエスト用) に限ります。このクラスを使用する目的は、保存されたURL で HTTP GET を実行することだけで、実行結果は FeedParser ライブラリーに渡します。それに続いて作成するのは、以下に記載する Entry クラスのインスタンスです。
リスト 7. Entry クラス
class Entry:
def __init__(self=None, title=None, link=None, timestamp=None,
content=None, service=None):
self.title = title
self.link = link
self.content = content
self.service = service
self.timestamp = timestamp
def printTime(self):
return strftime('%B %d,%Y at %I:%M:%S %p',self.timestamp)
|
このクラスの大部分は単純なデータ構造でしかありません。このクラスの唯一のロジックは、タイムスタンプを出力するためのメソッドの部分です。GenericFeed クラスは、ユーザーに関連付けられたサービスごとに Entry インスタンスのリストを返します。これらの Entry インスタンスは、タイムスタンプを基準に降順でソートします (最新の Entry が先頭)。次に MainPage に戻って、いくつかのオブジェクト、ユーザーの Account、ソートされた Entry のリスト、そしてログイン/ログアウト・リンクをテンプレートに渡します。GAE が使用するテンプレート・システムは、人気の Python フレームワーク、Django が使用するものと似ています。この例では、index.html という名前のテンプレートにデータを渡します。
リスト 8. index.html テンプレート
<html>
<body>
<a href="{{ url }}">{{ url_linktext }}</a>
<ol>
{% for update in updates %}
<li>
From {{update.service}}:
<a href="{{update.link}}">{{update.content}}</a>
posted at: {{update.printTime}}
</li>
{% endfor %}
</ol>
{% if account %}
<form action="/add" method="post">
<label for="service">Service: </label>
<select name="service">
<option>twitter</option>
<option>del.icio.us</option>
<option>last.fm</option>
<option>YouTube</option>
</select><br/>
<label for="username">Username: </label>
<input type="text" name="username"/>
<input type="submit" value="Add"/>
</form>
{% endif %}
</body>
</html>
|
これは単純なテンプレートで、その大部分は HTML でしかありませんが、動的な部分がいくつかあります。まず、該当するログイン/ログアウト・リンクを作成する部分。次にエントリーのリストを繰り返し処理して、ユーザーにエントリーを表示する部分。そして最後に、ユーザーがログインしている場合に、ユーザーがサービスを追加するためのフォームを作成する部分です。このフォームは /add URL に対して HTTP POST を実行します。リスト 3 で説明したように、リクエストは AddService コントローラー・クラスにルーティングされます。
リスト 9. AddService コントローラー
class AddService(webapp.RequestHandler):
def post(self):
# check if user already exists
account_query = Account.all()
account_query.filter('user = ', users.get_current_user())
result_set = account_query.fetch(1)
if len(result_set) > 0:
account = account_query.fetch(1)[0]
else :
account = Account()
account.user = users.get_current_user()
service = self.request.get('service')
username = self.request.get('username')
if service == 'twitter':
service = 'http://twitter.com/statuses/user_timeline/'+username+'.rss'
account.twitter = service
if service =='del.icio.us':
service = 'http://del.icio.us/rss/' + username
account.del_icio_us = service
if service == 'last.fm':
service = 'http://ws.audioscrobbler.com/1.0/user/'+username+
'/recenttracks.rss'
account.last_fm = service
if service == 'YouTube':
service = 'http://www.youtube.com/rss/user/'+username+'/videos.rss'
account.you_tube = service
account.put()
self.redirect('/')
|
このクラスはユーザーのアカウントを参照し、使用されたサービスに応じて適切な URL を作成します。そしてこの URL を、Expando プロパティーを使ってアカウントのサービスに追加した後、すべてを Bigtable に保存します。そして最後に、MainPage にリダイレクトします。
アプリケーションのコードはこれですべて説明したので、いよいよこのアプリケーションを実行する番です。アプリケーションの実行も、同じく Eclipse によって容易になります。
ローカル側でのテスト方法
GAE SDK には、プロジェクトをローカルで実行するためのコマンドライン・ツールが用意されています。ただし、ここでは Eclipse の利点を生かしたいので、Eclipse 内からアプリケーションを実行します。それによって、後で説明するようにアプリケーションのデバッグが可能になります。アプリケーションを実行する際の最初のステップは、PYTHONPATH をプロジェクトに合わせて編集することです。その最も簡単な方法として、プロジェクトを右クリックして Properties を選択してください。すると、プロジェクトのプロパティーが表示されます。
図 4. プロジェクトのプロパティー
上記の図に示されているように、まず左側のメニューで PyDev - PYTHONPATH を選択します。次に Add source folder をクリックして、GAE SDK がインストールされている場所までナビゲートします。この場所は使用している OS によって異なりますが、カスタマイズすることができます。Windowsでのデフォルト (インストーラーによる設定) は C:\Program Files\Google\AppEngine で、OS X でのデフォルトは /usr/local/google_appengine です。Linux を使用している場合、あるいはOS 固有のインストーラーではなく ZIP をダウンロードした場合には、SDK を配置する場所は任意に選択されているはずです。この場所はどこでも構いませんが、Eclipse が場所を認識できるようにしてください。ここでは、この場所を $APP_ENGINE_HOME と呼ぶことにします。
これで、後はプロジェクトを実行すればよいだけとなりました。プロジェクトを実行するには Run プロファイルを作成する必要があります。Run > Open Run ダイアログを選択してください。
図 5. Run ダイアログ
この Run プロファイルには aggroGator という名前を指定します。Main Module で、$APP_ENGINE_HOME をブラウズして dev_appserver.py スクリプトを選択してください。これは、GAE 実動環境を模倣する Python アプリケーション・サーバーです。次に、Arguments タブに進みます (図 6 を参照)。
図 6. Arguments タブ
Program arguments ボックスに、${project_loc}/src を入力します。Eclipse 変数 ${project_loc} は現行プロジェクトの物理ロケーションを指すだけに過ぎません。/src とあるのは、dev_appserver.py スクリプトにアプリケーションのディレクトリーを渡す必要があるためです。コードを置いてあるのが src ディレクトリーでない場合は、該当するディレクトリーに変更してください。
これで、アプリケーションを実行する準備ができました。Run をクリックすると、Eclipse コンソールにリスト 10 の出力が表示されるはずです。
リスト 10. コンソールの出力
INFO 2008-06-08 05:00:29,236 appcfg.py] Server: appengine.google.com
INFO 2008-06-08 05:00:29,283 appcfg.py] Checking for updates to the SDK.
WARNING 2008-06-08 05:00:29,581 datastore_file_stub.py] Could not read datastore data
from /var/folders/oo/ooKE4ln2HqC9exSMWxwprk+++TI/-Tmp-/dev_appserver.datastore
WARNING 2008-06-08 05:00:29,582 datastore_file_stub.py] Could not read datastore data
from /var/folders/oo/ooKE4ln2HqC9exSMWxwprk+++TI/-Tmp-/dev_appserver.datastore.history
INFO 2008-06-08 05:00:29,606 dev_appserver_main.py] Running application aggrogator
on port 8080: http://localhost:8080
|
この出力には、アプリケーションが http://localhost:8080 で実行中であることが示されています。以下のように、ブラウザーでこの場所にアクセスしてみてください。
図 7. aggroGator のウェルカム画面
Login をクリックすると、図 8 の画面が表示されます。
図 8. ログイン画面
もちろんこれは、偽のログイン画面です。Google 認証サービスに実際にアクセスすることにはならないため、どんな E メール・アドレスを使用しても構いません。実際、test@example.com というアドレスでもまったく問題ありません。ログインした時点から、サービスの追加を開始できます。
図 9. サービスの追加
ここからは、サービスを追加してアプリケーションをいろいろと試してみることができます。リスト 8 の AddService コントローラーをもう一度見ると、このクラスには、さまざまなサービスに対するフィードの URL がハード・コーディングされています。当然、この内容は将来変更される可能性があり、その場合にはエラーを受け取ることになります。そのような場合に重宝するのが、デバッガーです。次のセクションでは、この GAE プロジェクトで Eclipse デバッガーを使用する方法を説明します。
デバッグ方法
Eclipse のような IDE を使用する上での大きな利点は、複雑な Web アプリケーションでさえも、アプリケーションのデバッグが遥かに簡単になることです。GAE プロジェクトでデバッグを行うためには、まず Debug プロファイルを作成する必要があります。このプロファイルを作成するには、Run プロファイルと同じく、単にプロジェクトを選択し、Run > Open Debug ダイアログをクリックするだけです。
図 10. Debug ダイアログ
Eclipse の賢い機能により、このダイアログは前に作成した Run 設定にデフォルト設定されます。変更する必要はなく、単に Debug をクリックするのみです。Eclipse コンソールには、リスト 11 のような出力が表示されます。
リスト 11. デバッグの出力
pydev debugger: warning: psyco not available for debugger speedups
pydev debugger: starting
INFO 2008-06-08 05:18:37,704 appcfg.py] Server: appengine.google.com
INFO 2008-06-08 05:18:37,755 appcfg.py] Checking for updates to the SDK.
INFO 2008-06-08 05:18:38,196 dev_appserver_main.py] Running application aggrogator
on port 8080: http://localhost:8080
|
最初の 2 行に、pydev デバッガーからの出力が示されます。これで、プロジェクト内にブレーク・ポイントを設定してデバッグを開始することができます。図 11 でデバッグしているのは、AddService コントローラーです。
図 11. AddService のデバッグ
これで、コードをステップスルーして変数を検査できます。サービスのいずれかが変更された場合、あるいは新しいサービスを追加する必要がある場合には、この方法で簡単にバグを見つけて修正することができます。
まとめ
今回の記事では、アプリケーションの作成を一から始めて瞬く間に完成させました。Google App Engine SDK をインストールして Eclipse に接続したことによって、コードの作成、テスト、デバッグが簡単に行えるようになりました。この記事では、URL ルーティング、URL を取得することによる外部サイトとのやりとり、表示テンプレートの使用、そして Bigtable の操作をはじめ、GAE プロジェクトでの数々の重要な概念についても説明しました。サンプル・アプリケーションは GAE にデプロイする段階にまで来たので、第 2 回ではその方法を説明します。
ダウンロード | 内容 | ファイル名 | サイズ | ダウンロード形式 |
|---|
| Sample code | os-eclipse-mashup-google-pt1-aggrogator.zip | 74KB | HTTP |
|---|
参考文献 学ぶために
製品や技術を入手するために
議論するために
著者について  | 
|  | Michael Galpin は、1998年以来、プロとして Java ソフトウェアを開発してきています。彼は現在 eBay に勤務しています。彼は California Institute of Technology で数学の学位を取得しています。 |
記事の評価
|