2010年4月26日月曜日

bulkloaderでGeoPtのrestoreに失敗する

bulkloaderを使用してDataStoreにインポートしようとするときに、GeoPtプロパティが含まれていると失敗する現象が発生していました。
bulkloader.Loaderを継承してカンマ区切り文字列として渡してもダメで、
挙句の果てにはbulkloader.py --dump でダンプしたデータをrestoreしても失敗していました。
一度データを入れたアプリを落として、再度起動するとデータのリストアに失敗して立ち上がらなくなってしまうので、
これは根本的に駄目だなと。
ちなみに発生していたエラーはこんな感じ。

"unpack requires a string argument of length 8"

でこのエラーを頼りにググって調べた結果、Pythonのバージョンによるものだと。
http://code.google.com/p/googleappengine/issues/detail?id=401

というわけで、AppEngineのpython設定を2.6に切り替えたらうまく動きました。

2009年6月28日日曜日

GAEでphpのprint_rみたいな出力

phpではprint_rで配列や連想配列の中身を確認することが多いのですが、
pythonではそれに相当するものがなくデバッグに苦労しがちです。
そんなときには、配列や連想配列をjson形式で出力することで、同等に近い表示を行うことができます。


from google.appengine.ext import webapp
from django.utils import simplejson

def print_r(obj):
return simplejson.dumps( obj,indent=4,ensure_ascii=False)

class MainHandler(webapp.RequestHandler):

def get(self):
obj = {
"name" : "sample name",
"desc" : "sample desc",
"option" : {
"val1" : "value1",
"val2" : "value2",
"val3" : 333,
},
"arrary" : [
1,2,3,4,5
],
}

self.response.out.write( '<pre>' + print_r(obj) + '</pre>' )



jsonへ変換するときに、indentを設定してあげて見やすくするのと、
unicode文字列をasciiへエスケープする設定をoffにしています。
出力結果はこんな感じです。


{
"arrary": [
1,
2,
3,
4,
5
],
"name": "sample name",
"option": {
"val3": 333,
"val2": "value2",
"val1": "value1"
},
"desc": "sample desc"
}

2009年6月21日日曜日

Google App Engine でセッションを扱う方法

gaeutilitiesというプロジェクトで実現しています。

http://gaeutilities.appspot.com/

使い方はこんな感じ


#初期化
from appengine_utilities.sessions import Session
self.session = Session()

#セッションへ格納
session['key1'] = 'value1'

#セッションに格納されているか確認
if 'key2' in session:
#セッションの値を出力
print session['key2']


セッションの有効期間や
トークンをクッキーに保存するときの名称、
IPによるセッションの有効チェックなどを
初期化時に設定できるようです。


ざっとソースコードを眺めた感じ、cookie+storage+memcacheで実装されているようです。
同じようなコードを書いてしまいがちですが、車輪の再発明は避けたいですね。

2009年6月16日火曜日

URLFetchでPostする方法

urlfetchに引数を指定することでPostを投げる事もできます。
パラメータはpayloadに指定します。
urllib.urlencodeで文字列を生成することができます。



from google.appengine.api import urlfetch
import urllib

url = u'http://example.com/'
payload = urllib.urlencode( {
'param1' : 'value1',
'param2' : 'value2',
} )
response = urlfetch.fetch( url , payload , urlfetch.POST )

2009年5月31日日曜日

ElementTreeを使ってXMLを読み込む

マッシュアップには欠かせない、XMLのパース方法です。
xml.etree.ElementTreeを使います。



import xml.etree.ElementTree as etree

    xml = """
<test>
  <name>sample name</name>
  <desc type='text'>sample desc</desc>
  <option>
    <value>value1</value>
  </option>
  <option>
    <value>value2</value>
  </option>
  <option>
    <value>value3</value>
  </option>
</test>
    """

    elem = etree.fromstring(xml)
    self.response.out.write( '<br />name=' +  elem.findtext('name') )
    self.response.out.write( '<br />desc=' + elem.findtext('desc'))
    self.response.out.write( '<br />desc=' + elem.find('desc').text)
    self.response.out.write( '<br />desc type=' + elem.find('desc').get('type') )

    for opt in elem.findall('option'):
      self.response.out.write('<br />option ' + opt.find('value').text )   


2009年5月17日日曜日

Google Accounts のユーザー名は表示できない?

Google Accounts というGoogle の認証システムを使える便利な機能があるのですが、、、
http://code.google.com/appengine/docs/python/users/

これを使って、利用者本人を認証する分にはまったく問題ないのですが、
例えば、投稿データをこのUserクラスと関連づけようとすると問題が出てきます。

初期化のための変数が、emailアドレスしかないんですね。
ということは、ユーザー○○の投稿一覧ページなんかを作ろうとすると、
URLにemailアドレスを入れないといけない?
ということになってしまうような。。。

さらにnicknameというプロパティがあるのですが、
これもemailアドレスの@の前部分が返ってくるだけだし、
変更する機能なども特にサポートされていないようなんですね。

なので、何も考えずにユーザー投稿サイトを作ってしまうと、
gmailアドレスがダダ漏れなサイトになってしまいます。

emailアドレスは独自の暗号化して復元できないようにして、
nicknameは独自の編集機能を設けて
と自分で作り込むしかなさそうです。

Google Friend Connectとの連携が簡単にできるようになったりしないですかね?

2009年5月9日土曜日

unicodeとstringだけじゃない、db.Textはまた別です

UnicodeとStringが別物という話はpythonの世界では有名なようですが




Unicode で萎えそうになったとき(orz)に思い出してほしい5つのこと - Solr, Python, MacBook Airより引用:


Unicode 関係でモヤモヤしたら思い出してください。





GAEにはもう一つテキストを表す型があります。
ストレージに長い文字列を保管することができるTextPropertyがそれです。
一見するとStringと同じように動作するので紛らわしいのですが、直接Unicodeに変換することができず、一度stringに変換してあげる必要がありますので注意が必要です。



from google.appengine.ext import db

text = db.Text(u'あいうえお')

#これはエラー
#print text

#stringへ変換はOK
str = text.encode('utf-8')
print type(str) #

#unicodeへ直接変換できない
#uni = text.decode('utf-8')

#stringへencodeしてからdecodeしてunicodeへ変換可能
uni = text.encode('utf-8').decode('utf-8')
print type(uni)