2008年4月23日水曜日

Google App Engine Google Data Python Library


Getting Started with the Google Data Python Library

http://code.google.com/support/bin/answer.py?answer=75582

これはきちんと理解しておかないと、いろいろなエラーに時間をとられる。


C:\work\gdata.py-1.0.12.1>c:\python25\python ./setup.py install

-- gdata_test.py を変更

# from xml.etree import ElementTree
from xml.etree import ElementTree, SimpleXMLTreeBuilder
ElementTree.XMLTreeBuilder = SimpleXMLTreeBuilder.TreeBuilder
except ImportError:
# from elementtree import ElementTree
from xml.etree import ElementTre


C:\work\gdata.py-1.0.12.1>c:\python25\python ./tests/run_data_tests.py
Running all tests in module gdata_test...............
----------------------------------------------------------------------
Ran 15 tests in 0.031s
OK


サンプルプログラム muvmuv を下記からダウロ
ードして実行してみたのだが
http://code.google.com/support/bin/answer.py?answer=75582

起動
C:\google>dev_appserver.py muvmuv/
これはOK

実行
http://localhost:8080/build
しかし、これが NG

原因検索
http://groups.google.com/group/google-appengine/browse_thread/thread/b7399a91c9525c97

対策
http://effbot.org/downloads/ からelementtree-1.2.7-20070827-preview.win32.exe [52k]
を入れ、これを直接 project フォルダ以下に置いたが
C:\google\muvmuv\elementtree

結論としては windows SDK の不具合で fix 待ち 
http://code.google.com/p/googleappengine/issues/detail?id=222 this is a current issue with the Windows SDK.


--- その他 作業memo ---

Python版インストール(Windows) を参考に
PYTHONPATH=C:\Python25\Lib\site-packages を一応、設定

C:\google\muvmuv\ElementTree.py in ()
cannot import name SimpleXMLTreeBuilder

エラー例
Then I got "No module named expat: use SimpleXMLTreeBuilder instead".
'SimpleXMLTreeBuilder' is not defined

File "C:\google\muvmuv\main.py", line 235, in getMoviesFromRss
tree = ElementTree(fromstring(rss.content))
NameError: global name 'fromstring' is not define

Traceback (most recent call last):
File "C:\Program Files\Google\google_appengine\google\appengine\ext\webapp\__init__.py", line 484, in __call__
handler.get(*groups)
File "C:\google\muvmuv\main.py", line 215, in get
movies = self.getMoviesFromRss(rss1, build_only)
File "C:\google\muvmuv\main.py", line 235, in getMoviesFromRss
tree = ElementTree(fromstring(rss.content))
File "C:\google\muvmuv\elementtree\ElementTree.py", line 1013, in XML
return api.fromstring(text)
File "C:\google\muvmuv\elementtree\ElementTree.py", line 181, in fromstring
parser = XMLTreeBuilder()
File "C:\google\muvmuv\elementtree\ElementTree.py", line 1171, in __init__
self._parser = parser = expat.ParserCreate(None, "}")
NameError: global name 'expat' is not defined

---
Please see http://code.google.com/p/googleappengine/issues/detail?id=222 this is a current issue with the Windows SDK.

expat.py は pyexpat.py を import
コマンドラインからはエラーは発生しない DLLs/pyexpat.pyd などがある。

C:\google>c:\python25\pythonPython 2.5.2 (r252:60911, Feb 21 2008, 13:11:45) [MSC v.1310 32 bit (Intel)] onwin32Type "help", "copyright", "credits" or "license" for more information.
>>> from pyexpat import *


SDK102 にしたら build できた


最初起動時に simplejsonエラーが発生したが
以前どうやら django 以下に試行錯誤で置いた
ファイルをプロジェクトフォルダに copy して対応。


exec module_code in script_module.__dict__ File "C:\google\muvmuv\main.py", line 8, in import simplejson ImportError: No module named simplejson

 画像をクリックすると
 以下のエラーが発生しているが、これは
 対応できそうである。











File "C:\google\muvmuv\main.py", line 43, in get
template_values = {'login': loign, 'logout': logout, 'user': user}
NameError: global name 'loign' is not defined


2008年4月19日土曜日

Google App Engine /GqlQuery object and JSON


how to convert GqlQuery object to JSON format



http://groups.google.com/group/google-appengine/browse_thread/thread/634e7b9a2e584dd3?hl=en

How to use simplejson with GqlQuary object for example how to convert
marker_list to JSON for format
marker_list = db.GqlQuery('SELECT * FROM Marker')

I think you should dump queryset or row to python data, then convert
them to json format, here is my testing code:

def dumprow(r):
import datetime
a = {}
for k in r.fields().keys():
v = getattr(r, k)
a['id'] = r.key().id()
a['key'] = str(r.key())
if isinstance(v, str):
a[k] = str(v)
elif isinstance(v, unicode):
a[k] = unicode(v)
elif isinstance(v, datetime.datetime):
a[k] = v.strftime('%Y-%m-%d %H:%M:%S')
elif isinstance(v, datetime.date):
a[k] = v.strftime('%Y-%m-%d')
elif isinstance(v, datetime.time):
a[k] = v.strftime('%H:%M:%S')
elif isinstance(v, (int, float, list)):
a[k] = v
else:
a[k] = str(v)

return a

def dumpquery(query):
s = []
for r in query:
s.append(dumprow(r))
return s

Google App Engine 1.0.1 / sampels



Google App Engine SDK のバージョンが 1.0.1 になっていたので Update。
  http://code.google.com/appengine/downloads.html
 (アプリケーションの削除により、一旦削除してから、再度インストール)

 
また、google-app-engine-samples に登録されているものを、いくつか動かしてみた。
まず、これらのソースをながめてみるのがいいようだ。
http://code.google.com/p/google-app-engine-samples/downloads/list

Google App Engine Helper for Django  というものもある。
http://googleappengine.blogspot.com/2008/04/google-app-engine-helper-for-django.html
http://code.google.com/p/google-app-engine-django/

2008年4月14日月曜日

Google App Engine 入門7 検索まとめ

 

  こでまでの作業のまとめ
 以下が追加事項一覧です。

  1. dataJST を追加し、時刻を加工しJSTの時刻も合わせて登録するようにした。
    (が、時間の足し引きの値の理屈がどもう怪しい)
  2. 検索機能 (JQuery にて同じ画面内に絞り込んだ検索結果を表示)
  3. 該当件数表示
  4. Javascript (JQuery のライブラリ)を利用するようにした。
  5. スタイルシート main.css を多少加工した。
  6. イメージ画像の追加 ( app.yaml をよく理解していないこともあり、苦労した。Configuring an App もみてみたが、やはり実例がわかりやすい)
  • テンプレートを使用しないと datastore からの検索結果と同時に日本語を表示しようとすると UnicodeDecodeエラーが発生することから、これを利用。 やはりテンプレートは楽だと思います。

  • ただし、JQuery で検索結果をダイナミックに表示する部分はテンプレートは使用せずに直接記述しました。

  • テンプレートにタグを追加しようと調べたましたが、簡単ではないので中止。

Google App Engine 入門6 検索件数


Docs > Datastore API > Keys and Entity Groups の
Entity Groups, Ancestors and Paths の以下の部分は重要そうです。


When the application creates an entity, it can assign another entity as the parent of the new entity. Assigning a parent to a new entity puts the new entity in the same entity group as the parent entity.

An entity without a parent is a root entity. An entity that is a parent for another entity can also have a parent. A chain of parent entities from an entity up to the root is the path for the entity, and members of the path are the entity's ancestors. The parent of an entity is defined when the entity is created, and cannot be changed later.


データモデルについてはgoogle-appengine groupも議論が行われている 1:1,1:n 
Small tutorial on ER-modeling with GAE - 6 new
http://groups.google.com/group/google-appengine/t/aa26d529d66ac376?hl=en

  I wrote a small tutorial about ER-modeling with Google App Engine:
  http://daily.profeth.de/2008/04/er-modeling-with-google-app-engine.html


fulltext search機能の現状について  Indexing Large Chunks of Text for Search
 There's no ranking, which is a killer drawback. (致命的欠点)
 no exact phrase match, substring match, boolean operators,
 support for stop words (common words that are not indexed) is currently limited to English.


・検索結果の件数について

Docs > Datastore API > GqlQuery を参考
* bind()
* get()
* fetch()
* count()

greetings = Greeting.all().order('-date')
row_cnt = greetings.count()
で件数をカウントすることができました。

Google App Engine 入門5 検索


Datastore API > Creating, Getting and Deleting Data にQuery と GqlQuery の2通りの例がありますが、今回は Query を利用してみます。


1. 単純動作テスト 検索条件の追加
content の値が 'Foo'  のものだけ表示するようにしてみます。
greetings = Greeting.all().order('-date')
greetings.
filter('content =', 'Foo')       # 追加
これは素直に動作しました。

2.  Key とは ?

rowid にあたるような、ものがあります。
unique key that represents the object.
Doc だと APIs > Datastore API > Reference > Key です。

The key() method で得た値(Key object)を put() in the datastore したりすると NotSavedError エラーになるとあります。 RDBMS の場合の一意制約違反のエラーのようなものだと思います。

instance for a given Key using the get() function.
この部分は実際のデータをみてみないとこの先の機能の意味がつかめそうもありません。
key = greeting.key()
self.response.out.write('%s' % str(key) )
self.response.out.write('%s' % greeting.get(key) )
          このような値が返ってきていました。
agpoZWxsb3dvcmxkcg4LEghHcmVldGluZxgTDA
<__main__.Greeting object at 0x02600B30>
なるほど、key がわかれば、 get(key) でたどって実際の値もわかるということです。

key の理解にはReferenceProperty model とういうのもポイントのようです。
あと、ancestor() methods on the object というのが、まだよく理解できていません。


さて、ようやくある程度、検索が動作すようになったと思っていたら、日本語からみのいやなエラーが発生しだしました。

body 内に日本語を使用する self.response.out.write("日本語") だけでエラーとなります。 
INFO 2008-04-16 16:24:10,546 dev_appserver.py] "GET / HTTP/1.1" 500 -
Traceback (most recent call last):
File "C:\Python25\lib\wsgiref\handlers.py", line 92, in run
self.result = application(self.environ, self.start_response)
File "C:\Program Files\Google\google_appengine\google\appengine\ext\webapp\__i
nit__.py", line 504, in __call__
response.wsgi_write(start_response)
File "C:\Program Files\Google\google_appengine\google\appengine\ext\webapp\__i
nit__.py", line 223, in wsgi_write
body = self.out.getvalue()
File "C:\Python25\lib\StringIO.py", line 270, in getvalue
self.buf += ''.join(self.buflist)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe3 in position 13: ordinal
not in range(128)
発生するようになったタイミングはこの部分の追加以降
greetings = db.GqlQuery("SELECT * FROM Greeting ORDER BY date DESC LIMIT 10")
for greeting in greetings:
if greeting.author:
self.response.out.write('wrote:' )
self.response.out.write('%s wrote:' % greeting.author.nickname())
else:
self.response.out.write('An anonymous person wrote:')
self.response.out.write('%s' %
cgi.escape(greeting.content))


困ったものです
self.response.headers['Content-Type'] = 'text/html'
self.response.headers['charset'] = 'UTF-8'
では効果なし。
発生例はかなり報告されていますが・・・

いろいろ試してもうまくいきませんが、テンプレートを利用した場合はこうした日本語の問題は発生しないようですので、やはりテンプレート利用する方向になりそうです。

Google App Engine 入門4 Pythonで時差の処理




テンプレートの利用はあきらめて、Python 本体にて時刻の計算処理を行うことにしました。 (index.html でなく helloworld.py を変更)

Types and Property ClassesDatastore Value Types datetime.datetime に説明があります、
さらに詳細は Python へ  the datetime module documentation. のリンクとなています。
日本語だとこのあたりが timedeltaオブジェトなのですが、Python 自体に慣れていないので、実際に動作テストしてみました。

Pythonによるテストのため、まず PATH=C:\Python25  を追加しておきます。
環境変数 TZ による影響があるようです。

C:\google\helloworld>set TZ=
C:\google\helloworld>python
Python 2.5.2 (r252:60911, Feb 21 2008, 13:11:45) [MSC v.1310 32 bit (Intel)]
>>> import datetime
>>> print datetime.datetime.now()
2008-04-14 13:17:36.953000
>>>

C:\google\helloworld>set TZ=JST
C:\google\helloworld>python
Python 2.5.2 (r252:60911, Feb 21 2008, 13:11:45) [MSC v.1310 32 bit (Intel)]
>>> import datetime
>>> print datetime.datetime.now()
2008-04-14 04:21:32.015000
>>>
Ctl+Z で終了
-- test scrit tt.py
import datetime

class JST(datetime.tzinfo):
def utcoffset(self, dt):
return datetime.timedelta(hours=9)
def dst(self, dt):
return datetime.timedelta(0)
def tzname(self, dt):
return "JST"

print datetime.datetime.now().isoformat()
print datetime.datetime.now(JST()).isoformat()
実行結果
C:\google\helloworld>python tt.py
2008-04-14T04:28:33.468000
2008-04-14T13:28:33.468000+09:00

まずは、 helloworld.py の class MainPage にて以下のように出力するようにしました。
for greeting in greetings:
・・・
d = greeting.date + datetime.timedelta(hours=9)
self.response.out.write('%s
' % d.strftime("%Y/%m/%d %H:%M:%S") )
として対応することにしました。

参考
Pythonで現在の日付を取得してフォーマットする
http://www.r-stone.net/blogs/satoshi/2008/02/python.html

Unityでドアの開閉はAnimatorそれともiTween?

Mac Mini M2 の Unity で Sketchup のデータを復元したつづき。 以前、苦労して作成したドアの開閉が動作しないので修復する。 どうやって動かしていたのか、また忘れそうなので記録しておく。             Animator 左右のドア PlaneL,...