Sinatraライクなmicro web application framework `Dancer`をインストールしてみた

Posted at 2010-06-23T17:22:10+09:00 in Coding

Dancerをインストールしたときに詰まったことのメモ

簡単なWeb Applicationを作りたいなと思い、Web Application Frameworkを物色していたのですが、 とりあえずPSGI/Plackを見て、Dancerがよさげだったので、 とりあえずインストールしてみました、という話。

で、DancerはCPANにuploadされているので、いつものように、

$ cpan
(省略)
cpan[1]> install Dancer

としたのですが、なんかいくつかのテストがFAILしました。

で、とりあえずcpan shellで、

cpan[2]> look Dancer

として、prove使ってテストを手動で実行するものの、同じところでFAIL。

んで埒が明かないということで、実際のテストコードを見たところ、 どうもDancerの実装とは直接関係なさそうな、HTTPレスポンスやらのパースでこけてるっぽかったので、 これは多分LWPが古いせいだろうということで、

cpan[3]> i LWP

として(実際にはi HTTP::Messageとしてたけど)LWPのバージョンを確認、 するとちょっとばかりバージョンが古かった(メモってないので元のバージョンは忘れた)ので、

cpan[4]> install LWP

としてLWPをアップデート。

と思ったら、これもまたなんかテストがFAILしてたので、 多分LWPが使用している関連モジュールが古いせいじゃないか? と思って、LWPMakefile.PLを閲覧、cpan shellで片っ端から依存モジュールを

cpan[5]> i {module}
(バージョンが出る)
cpan[6]> install {module} # 古かったらアップデート

という感じでアップデートして、もう一回

cpan[7]> install LWP

したところ、今度はちゃんとテストが通って、アップデートが終了した。

んで、これでもう大丈夫だろうということで、

cpan[8]> install Dancer

して、今度はちゃんとテストも通りモジュールもインストールされました。

まあ今回いえることは、他のモジュールでもそうですが、 他のtestersの環境ではテストが通ってるのに、自分の所でテストが妙な感じでFAILする場合は、 依存モジュールを最新のにアップデートすると問題が解決する場合がある、 という感じです。

まあもっともアップデートに慎重さが要求される場合、例えばCatalystのMooseへの移行とか、 モジュールに大きな変更が加えられた場合なんかには、 依存モジュールをうかつにアップデートするとはまることになるかも知れません。

とりあえず今回はDancerをインストールする際にLWPのアップデートが必要だった、 ってことをメモしておきます。

まあDancerの使い方はこれから調べることにしよう。

Mako template engine on Google App Engineでmemcacheを使う方法、試作編

Posted at 2010-06-18T17:01:53+09:00 in Coding

PythonのテンプレートエンジンmakoでGoogle App Engineのmemcacheを使う方法(確証なし)

最近、というか2,3日前からGoogle App Engineで動く大規模掲示板スクリプトを作り始めたんですが、 その掲示板スクリプトで使ってるテンプレートエンジンのmakoで、 Google App Engineのmemcacheを使ってテンプレートのキャッシュをする方法を紹介したいと思います。

で、makoはキャッシュシステムとしてbeakerを使ってるらしいんですが、 このbeakerでGoogle App Engineのmemcacheを使うようにすると、makoをGoogle App Engineのmemcacheに対応させられる、 というのが本題です。

まあこの対応の仕方はほぼネットにあった

のコードまんまなんですが、大体こんな感じです。

def patch_beaker():
    import sys
    import google.appengine.api.memcache

    # 1) alias `memcache` = `google.appengine.api.memcache`
    sys.modules['memcache'] = google.appengine.api.memcache

    # 2) disable access to local files.
    import beaker.ext.memcached
    from beaker.synchronization import null_synchronizer

    beaker.ext.memcached.verify_directory = lambda x: None
    beaker.ext.memcached.MemcachedNamespaceManager.get_creation_lock = lambda x, y: null_synchronizer()

try:
    patch_beaker()
except Exception:
    raise

一応解説すると、

まず最初の1)の部分で、モジュールmemcachegoogle.appengine.api.memcacheにエイリアスしています。 Google App EngineのmemcacheモジュールはPythonのmemcacheモジュールと互換性があるので、 このそのまま代入で多分動きます。

次に2)の部分ですが、ここではbeaker.ext.memcachedのローカルのファイルにアクセスしている部分をつぶしています。 まあこれも多分うまく動くんでしょう。あんまり検証してませんが。

で、これでbeakerへのパッチは終了で、今度はmakoのコードに入っていきます。

んで、上記のコードが書いてあったUse beaker and mako with memcacheでは、 makoのコードをいじくりまわして対応させてるんですが、元のコードが書かれたのは2008年10月23日で、 その当時のmakoのコードと、2010年06月18日現在のmakoのコードとはかなり違っているみたいなので、 当時のコードを現在のmakoに適用しても、当然のことながら動きません。

で、現在のmakoのコードを見てみたのですが、今のmakoはbeakerを使った(と思われる)キャッシュ機構がキチンと備わっており、 そのキャッシュ機構をそのまま使えば問題ないっぽいです。

で、実際のmako側のコードはこんな感じになります。

from mako.template  import Template
from mako.lookup    import TemplateLookup

lookup = TemplateLookup(
    # temlate dir
    directories=[ '/path/to/template/dir' ],

    # enable cache
    cached=True,
    cache_type='memcached',
    cache_urt='memcached://',
)

template = lookup.get_template('template.tmpl')

print template.render(foo='bar')

ポイントとしては、最初に書いたbeakerへのパッチを有効にした後、 cache_typememcachedに指定する、という所でしょうか。 当然のことですが、このcache_typefileとかにすると、Google App Engineでは動きません。

で、ポイントさえ押さえれば、あとは普通にmakoを使えば良いっぽいです。

んで一応注意しておくと、ローカルの環境で、makoを使ったテンプレートエンジンクラスを、 noseNoseGAEを使ってテストした限りでは特に問題なく動きましたが、 実際のGAE環境ではテストしていないので、本当に実環境で動くかどうかはよくわかりません。 が、ローカルの環境では動いてるように見えるので、多分大丈夫だとは思います。

というわけでmakoでGoogle App Engineのmemcacheを使ったキャッシュを行うという話でした。

Pythonではライブラリのディレクトリと同じファイル名のファイルは無視される(?)

Posted at 2010-04-10T20:08:40+09:00 in Coding

Pythonのライブラリのimportではまったときのメモ

どういうことか

例えばこういうディレクトリ構造があったとする

~/dev/{project}/
    {appname}/
        __init__.py
        library.py
        library/
            __init__.py
            childlib.py

このディレクトリ構成で、{appname}/library.pyを読み込みたいとしても、 どうも{appname}/library/__init__.pyが読み込まれるっぽいので、 {appname}/library.pyは読めないっぽいです。

ちなみにPerlだと

~/dev/{project}
    {appname}/
        Library.pm
        Libary/
            ChildLib.pm

という感じの構成になりますが、こっちだと問題なく読めたりする

まあこの仕様(?)に今日一日中はまってました。

感想

Perlで動くんだから、Pythonでも似たようなもんだろうと思ってたら、 全然違ったという。まあ分からないこと解決したんで、なんとかなりそうです。

あれだ、PythonってPerl使いにとっては異文化そのものだよ!(他の言語でも一緒かな)

dev_appserver.pyに関するメモ

Posted at 2010-04-09T16:42:33+09:00 in Coding

Google App Engineのdev_appsever.pyに関するメモ

注意

この記事は今日Google App Engineのdev_appserver.pyで大はまりした事についてまとめた記事なのですが、 とりあえず解決した本人も何が悪かったのかよく分かってないため、 要領を得ない記事になってるかもしれません。

したかった事

要するにこういうディレクトリ構成でdev_appserver.pyを動かしたかった

~/dev/{project}
    # アプリケーション関連ファイルのディレクトリ
    app/
        {appname}/
            app.yaml
            script.py
            ...etc
    # アプリケーションの実行に必要なファイルのディレクトリ
    lib/
        {project}/
            {module}.py
            __init__.py
            ...etc

できなかった事

上記で言うapp/{project}/script.pyで、lib/{project}へのパスを通しても、 なぜかdev_appserver.py経由では読み込んでくれないという現象に遭遇した。

ちなみにapp/{project}/script.pyをshellから直接実行した場合はきちんと動く

仮説

もしかすると、dev_appserver.pyは任意のディレクトリからはライブラリを読めない?

検証

とりあえず上記で言うlib/{project}app/{appname}/以下にコピーしたところ問題なく動いた。

とりあえずの解決策

lib/{project}の内容は、複数のGAE Applicationで共有したい、と考えていたので、 とりあえずapp/{appname}/以下にlib/{project}のシンボリックリンクを貼ることによって何とかなった。

要するにこんな感じ。

~/dev/{project}
    app/
        {appname}/
            app.yaml
            script.py
            {project}   # これがシンボリックリンク
    lib/
        {project}/      # ここがシンボリックリンクのリンク先
            {module}.py
            __init__.py

分かってないこと

色々と検索してみたものの、上記の現象がdev_appserver.pyの仕様なのか、 バクなのか、それとも俺のやり方が悪かったのか、というのはよく分かってません。

まあとりあえずはシンボリックリンクでなんとかなったのでよしとしよう。

ちなみに

これを解決するまでに一時間半かかりました。

で、とりあえず解決はできたので、長いこといってなかった床屋へ行き、 サッパリして帰ってきた後この記事を書いてます。

とりあえず自分も今回の件についてよく分かってないので、 断片的に情報をまとめてみた次第。

たぶん他の人には分かりづらいと思うけど、自分用のメモということで。

Google App Engine PythonでとてもシンプルなWSGI Applicationを動かす方法

Posted at 2010-04-07T17:11:50+09:00 in Coding

AppEngine PythonでとてもシンプルなWSGI Applicationを動かす

こんにちま!いつも心にwhile True: pass!悪い意味でパソコンが恋人、岡村直樹(22)です。 書き出しの部分をファウストで連載してるユヤタンの人生・相談のパk……じゃない、 パロディで始めてみました。みなさんゴリュゴリュとコード書いてますか?

……というわりと書くのだけは楽しげな事は置いといて、 最近というか前にGoogle App Engineの記事を書いてから、 初めてのPythonを読み進めてクラスについてのあたりまで読破して、 Google App Engine用Applicationも書けるようになったかな?ということで、 Google App Engine上ですごくシンプルなWSGI Applicationを動かせた!ということを記事にしたいと思います。

(前置き長いな……。)

まあそれはいいんだけど、Pythonistaにとっては常識かも知れませんが、 僕の理解が間違っていなければ、WSGIというはWeb Server Gateway Interfaceの略で、 Web ApplicationとWeb Server間の情報のやり取りについてまとめた、 仕様の一種です。(ちなみにPerlで最近になってできたPSGIの仕様はWSGIが元になってます)

で、WSGI ApplicationというのはこのWSGIの仕様に沿った関数またはクラスのことを言うのですが、 (理解が間違っていなければたぶんあってると思う……) 今回は関数で書かれたWSGI ApplicationをGoogle App Engineのdev_appserver.pyで動かしてみたよ! ってのをメモって置きたいと思います。

まあこれはコード書けば早いんですが、WSGI ApplicationをGoogle App Engineで動かすには下記のようになります:

# wsgi applicationを走らせる関数をインポート
from google.appengine.ext.webapp.util import run_wsgi_app

# とてもシンプルなwsgi application
def application ( environ, start_response ):
  start_response('200 OK', [('Content-Type', 'text/plain')])
  return 'hello world!'

# ファイルの実行部分
def main ():
  # この関数がwsgi applicationを実行する
  run_wsgi_app(application)

if __name__ == '__main__':
  main()

解説はまあコメントに書いてあるとおりで、def application( environ, start_response ):でWSGIの仕様に沿った関数をつくり、 関数run_wsgi_appで実際にWSGI Applicationを走らせるという感じです。

まあ最初Google App EngineもPythonもWSGIも完全初心者状態で書いてたので、 ここまでたどり着くのにはそれなりに時間がかかったのですが、 まあ書いてみたら案外たいしたこと無かったというオチでした。 まあでもちゃんと動いたときはちょっと感動しましたヨ。

ちなみにWSGIに沿った関数を動かすにはこんな感じですが、 これがクラスの場合だとどうなるのかサッパリ分かってません>< ま、コレはこれからPythonの学習やGoogle App Engineのアプリケーションのコード書いていけば分かってくるかと思いますが。

とりあえず今日はみょーなテンションでこの記事を書いてますが、これで書きたかったことは以上です。 というわけでGoogle App Engine上でシンプルなWSGI Applicationを動かしたよ!というメモでした。

About Me

name
Naoki Okamura
nick
nyarla
contact
nyarla[ at ]thotep.net
Category
Log
Banners
Powered by
nim