2008年10月25日土曜日

第4回Python温泉 参加中 2日目

- 8:00
起床。眠い!

- 9:00〜11:00
持ち込んだカルドセプトDSが大活躍してくれました。

- 11:20
温泉でさっぱりしたところで仕事開始。
まずは昨日のまとめを行う。増田さんと俺の違いは何?何を改良すればあのように優れたハッカーになれるか?

- 12:00
お昼ご飯を食べながら会社の仕事をやったりメールチェックしたりRSSをチェックしたり

- 13:00
来宮神社まで遊びにいく、神社まで遊びに行くというと、某吸血幼女が頭に浮かんだりするがいっさい関係ないと思います

- 14:23
神社に行く予定がなぜか途中の有名人の別荘に足を取られて1時間以上ガイドの人のお話を聞くことに・・・
遅れている仕事を取り戻す

- 16:05
django.conf.globalsettings.py

# List of processors used by RequestContext to populate the context.
# Each one should be a callable that takes the request object as its
# only parameter and returns a dictionary to add to the context.
TEMPLATE_CONTEXT_PROCESSORS = (
'django.core.context_processors.auth',
'django.core.context_processors.debug',
'django.core.context_processors.i18n',
'django.core.context_processors.media',
# 'django.core.context_processors.request',
)
django.core.context_processors.mediaがメディアファイルのURLをテンプレートに渡されるコンテキストに勝手に渡してくれる
strutsに例えるならば、request.setAttritebute()を勝手に裏でやってくれるところ
ここで、
    return {'MEDIA_URL': settings.MEDIA_URL}
としているので、テンプレートの中でMEDIA_URLが使えるはず。使ってみよう

- 20:03
4時間ぐらいずっとdjango.views.static.serve()について悩みっぱなし。
設定は絶対に間違っていないはずなのに、staticファイルが何度やっても読み込めない・・・なぜ?
こんなエラーが出る:
Page not found: /Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/django/contrib/admin/media/css/django_todo.css
一体全体どうしてdjango/contrib/adminなんて所を見ているのかどうかわからない・・・

- 20:10
増田さんありがとう(またかよ)!
つまりはこういうことでした。settings.pyの以下の行が原因。

# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a
# trailing slash.
# Examples: "http://foo.com/media/", "/media/".
# MEDIA_URLやdjango.views.static.serveのdocument_rootと同じ値を設定すると、
# django.adminの要求するパスとかぶってしまうためうまく動かない!
ADMIN_MEDIA_PREFIX = '/media/'
#ADMIN_MEDIA_PREFIX = '/admin_media/' のように書き換えればうまくいくことがわかりました
これでなんとか先に進めそうだ!ラストスパート!!

- 23:19
無事にJavaScriptとCSSを参照することに成功するものの、こんどはUnicodeとJSONではまってしまう・・・
1:'\u71c3\u3048\u308b\u30b4\u30df\u3092\u51fa\u3059\u7528\u610f\u3092\u3059\u308b'こんな感じの文字列で画面に送られてきてしまう。日本語として出したいのだが・・・
2:そもそもJSONがeval()できない!
eval('{a:b}');
これを実行するとエラー・・・

1時間近く格闘して解決。まず1については、これは評価されていない素のユニコード文字列だから。これをそのままtext/plainとして画面に出しているから記号のまま画面に出てしまうようだ。Python側でこれをどうこうすることはできない(Unicodeとして正しいから。出力時に勝手にきちんとした日本語にされる訳で、データとしてはユニコードとして正しい。u'\u71c3'とu'燃'は全く同じ。)解決するためには、いったんこの文字列をJavaScriptでevalして評価してもらう必要がある。

2については、そもそもJSONとして形式が間違っている。
プロパティ名と値はクオテーションする必要がある。
eval('{"a":"b"}');
これが正しい。しかしこれでもエラーになる。なぜか?
http://d.hatena.ne.jp/language_and_engineering/20081022/1224597688
このページをみて解決。まさに書いてある通り。
全体を括弧で囲まないと、"a"がジャンプ用ラベルとして扱われてしまう。括弧で囲めば{}以下がオブジェクトとして扱われる。
ということで、正解はこう
eval('({"a":"b"})');
JSONでやたら括弧が多い理由がやっとわかった!!
それにしても、たかがJSONと思って驕り高ぶっていたらひどい目にあった・・・己の無知を痛感。

2008年10月24日金曜日

第4回Python温泉 参加中 1日目

- 11:40
宿に到着、こんなに坂の上とは思わなかった

- 12:30
近くの来宮神社でうどん、なかなか美味しい
雨が降っていなければまたきて写真撮ろう

- 13:00
RTMにアクセスするだけの簡単なDjangoアプリを作ってみることにする
http://www.rememberthemilk.com/services/api/
http://repo.or.cz/w/pyrtm.git
こいつのソースを解析してRTMへのアクセス方法を調べる予定、まずは後回しにしてdjango側からつくってゆく

- 14:00
全員黙々とプログラミング作業中、なんだか会社にいるときよりまじめに仕事している俺がいる
さすがにこの空気で遊ぶ訳には・・・

- 15:42
なんとかURLとviewの設計まで完了、まだHelloWorldレベル
Modelは全然使ってないです^^

誰でも知っているどうでもいいTips:
Mac OS Xのpythonのインストール先はなんだか特殊なのでwhichして調べよう
   akisute bin$ which python
/Library/Frameworks/Python.framework/Versions/Current/bin/python
akisute bin$ cd /Library/Frameworks/Python.framework/Versions/Current/bin/python

2行目をコピーして、/bin/pythonを/libに書き換えるといい感じ。/lib/python2.5/site-packages以下がみんな大好きサイトパッケージです
後々の実験のために、ここのsite-packagesにrtm.pyをおいておく

- 16:03
そろそろRTMへのアクセスが必要なので、rtm.pyの解析を行うことにした
パブリックメンバーとして用意されているメンバーは4行目に定義されている
   __all__ = (
'API',
'createRTM',
'set_log_level',
)

あとtest()も自由に使えるようだ。
どうやらcreateRTM()すれば基本万事解決みたいですね。
ここでapiKey, secret, token, frob, signといったよくわからない単語が多数登場。RTMのAPIリファレンスをみて勉強し直すことにする

- 16:50
WireSharkなるソフトウェアが話題になる。
(パケット監視ソフトウェアらしい)
Mac OS XではCocoa動作ではなくてX11(多分GTK)で動作するとのこと
・・・こんなのを使うのかよ

- 17:22
RTM APIシステムについて調査完了。別記事にして詳しく書きます。腹減った・・・

- 18:12
温泉に入ってきました。さすが源泉掛け流しだぜ・・・いい湯でした

- 18:42
rtm.pyの使用により、RTMからタスク一覧を取得することに成功!
しかしrtm.pyが例外を吐いて止まってしまいました。
Traceback (most recent call last):
File "", line 1, in
File "rtm.py", line 381, in test
print [t.name for t in rspTasks.tasks.list.taskseries]
AttributeError: 'list' object has no attribute 'taskseries'
ソースを追ってみると・・・384行目
rtm = createRTM(apiKey, secret, token)
rspTasks = rtm.tasks.getList(filter='dueWithin:"1 week of today"')
print [t.name for t in rspTasks.tasks.list.taskseries]
さらに追いかける・・・85行目から
def get(self, **params):
"Get the XML response for the passed `params`."
params['api_key'] = self.apiKey
params['format'] = 'json'
params['api_sig'] = self._sign(params)
json = openURL(SERVICE_URL, params).read()
LOG.debug("JSON response: \n%s" % json)
if _use_simplejson:
data = dottedDict('ROOT', simplejson.loads(json))
else:
data = dottedJSON(json)
rsp = data.rsp
if rsp.stat == 'fail':
raise RTMAPIError, 'API call failed - %s (%s)' % (rsp.err.msg, rsp.err.code)
else:
return rsp
rsp.statにはアクセスできるが、
rspTasks.tasks.list.taskseriesにはアクセスできない・・・
返ってきたJSONをよく見てみる
{"rsp":{"stat":"ok","tasks":{"list":[{"id":"3161896","taskseries":{"id":"......
なるほど、listがリストになっている。
rspTasks.tasks.list[0].taskseriesというふうにしなくちゃならないんだな。

- 21:26
ご飯も食べ終わってそれでもひたすらソースを書き続ける・・・
引き続きDjangoのview作成を進めるが、rtm.pyの結果をJSON形式にできないことが判明(DottedDictという特殊な型)
自分でJSON変換を書くしかないのかな?オブジェクトをJSONに変換するライブラリなんていくつもありそうだけど

それからもう一つ問題が、
Djangoのデバッグ時のエラー画面(エラーの詳細情報を表示してくれる)がうまく表示されない。

TemplateSyntaxError: Caught an exception while rendering: unknown encoding: X-MAC-JAPANESE

- 22:34
増田さんがあっというまに問題を解決してしまいましたとさ・・・
かろうじて何をやっているのか見えた箇所をメモ
find -r? ./ -name 'sitecu*.py'
C Pythonを使ってC言語のstdlibのlocaleモジュールにアクセス?
QuickSilverを利用?
export LANG=ja_JP; python
>>> import sys
>>> dir(sys)
>>> sys.getdefaultencoding()
>>> import locale
>>> print locale.getdefaultlocale()
>>> assert False, locale.getdefaultlocale()
>>> print '\n'.join(sys.path)
python -vで読み込まれたパッケージがすべて表示される
/usr/local/bin以下のシンボリックリンクをdmgパッケージからインストールしたPython.org公式のPythonが上書き(というか優先的に読み込み)している
結論から:
1:python.org公式の2.6にアップグレードする。問題が修正されている。
2:/System/Library以下のPython2.5.1を利用する、Macシステム標準のPythonはMacPortsから大量のパッチがあたっているらしい。
公式の2.5.2はそれらのMac用のパッチがあたっていないためそのような問題が起きる・・・?
(Cocoaを利用してロケールを読み込んでいるから?envを無視している?)
3:どちらもいやなら、sitecustomize.pyを作って修正を書き込む

よくわからないがとにかくpythonを2.6にアップグレードするのが最善なようだ。

- 0:46
python2.6へのアップグレードは問題解決にならなかった。
確かにパッチはあたっていたが、locale.getdefaultlocale()の値を書き換えるようなパッチではなく、
getdefaultlocale()の値がX-MAC-JAPANESEの場合はsjisに振り返るようにしているだけで、
直接locale.getdefaultlocale()の値を利用しているdjangoの場合には使えないようだ。

locale.getdefaultlocale()が正しい値を返すようにするにはAppleがビルドしたpython(パッチ適用済み、要するに2.5.1)を使うしかない。

そこで回避策を考えつかれた:
エラーで落ちる原因はX-MAC-JAPANESEを処理するためのcodecが登録されていないから見つからないでLookupErrorになっている
X-MAC-JAPANESEの正体は単なるshift-jisなので、shift-jisのコーデックを利用して新たにX-MAC-JAPANESEのコーデックを登録すればいいということらしい。

あっというまにパッチが完成、試してみると・・・見事に通った!これがハッカーの仕事か・・・

あとFinderで隠しファイルを表示したり/usr/binを表示する方法が地味にわかった
http://goonsh.ddo.jp/fg/2005/01/18/on-finder
http://netafull.net/macosx/014755.html

Spotlightの有用性もわかった
明日はQuickSilverを入れてみることにする

今日はもう寝る!!

よくわかるユニコード

  • Unicodeは文字コードセットのこと。UTFとは別。
  • UTF-何々というのはUnicodeをのエンコード方式のこと。
  • BOM(Byte Order Mark)は基本的にUTF-16にしかつかない。UTF-8では不要。
近頃はWeb上のリソースから、iPhoneの文字列までみんなUnicodeになりましたね。
でもよく考えたらUnicodeについて真面目に学んだことが一度もなかったので、BOMのあるなしで悩んだのをきっかけに、Unicodeについて勉強してみました。

勉強しただけではすぐ忘れちゃうので、こんな図にしてみました。




これで少しは覚えられるかも。