2008年6月20日金曜日

Importing UTF-8 Data with Bulkloader

Importing UTF-8 Data
http://groups.google.com/group/google-appengine/browse_thread/thread/d4cf3013483220b5
を参考にいろいろ試したが、以下のパターンで UTF-8 が登録できたが、
str とタイプが決まってしまて、 datastore_types.Text にできなかったので
500 バイト以上の UTF-8 データについては別途検討。

myloader.py

#from google.appengine.ext import bulkload
import bulkload
・・・
class PersonLoader(bulkload.Loader):
def __init__(self):
# Our 'Person' entity contains a name string and an email
bulkload.Loader.__init__(self, 'Person',
[
#      ('name', str),
      ('name', lambda x: unicode(x,'utf-8')),
('email', datastore_types.Email),
])


bulkload をフォルダごとProjectフォルダにコピーして、__init__.py を加工。
bulkload/__init__.py
・・・
buffer = StringIO.StringIO(data.encode('utf-8'))
・・・


('name', lambda x: unicode(x,'utf-8')) をやめて、以下を追加すると
日本語がきれいに抜けて、英数字だけになる。
#     val =  unicode(val, errors='ignore')
entity[name] = converter(val)

bulkload/__init__.py

c:/Program Files/Google/google_appengine/google/appengine/ext/bulkload/
__init__.py


"""A mix-in handler for bulk loading data into an application.

For complete documentation, see the Tools and Libraries section of the
documentation.

To use this in your app, first write a script, e.g. bulkload.py, that
instantiates a Loader for each entity kind you want to import and call
bulkload.main(instance). For example:

person = bulkload.Loader(
'Person',
[('name', str),
('email', datastore_types.Email),
('birthdate', lambda x: datetime.datetime.fromtimestamp(float(x))),
])

if __name__ == '__main__':
bulkload.main(person)

See the Loader class for more information. Then, add a handler for it in your
app.yaml, e.g.:

urlmap:
- regex: /load
handler:
type: 1
path: bulkload.py
requires_login: true
admin_only: true

Finally, deploy your app and run bulkload_client.py. For example, to load the
file people.csv into a dev_appserver running on your local machine:

./bulkload_client.py --filename people.csv --kind Person --cookie ... \
--url http://localhost:8080/load

The kind parameter is used to look up the Loader instance that will be used.
The bulkload handler should usually be admin_only, so that non-admins can't use
the shell to modify your app's data. The bulkload client uses the cookie
parameter to piggyback its HTTP requests on your login session. A GET request
to the URL specified for your bulkload script will give you a cookie parameter
you can use (/load in the example above). If your bulkload handler is not
admin_only, you may omit the cookie parameter.

If you want to do extra processing before the entities are stored, you can
subclass Loader and override HandleEntity. HandleEntity is called once with
each entity that is imported from the CSV data. You can return one or more
entities from HandleEntity to be stored in its place, or None if nothing
should be stored.

For example, this loads calendar events and stores them as
datastore_entities.Event entities. It also populates their author field with a
reference to the corresponding datastore_entites.Contact entity. If no Contact
entity exists yet for the given author, it creates one and stores it first.

class EventLoader(bulkload.Loader):
def __init__(self):
EventLoader.__init__(self, 'Event',
[('title', str),
('creator', str),
('where', str),
('startTime', lambda x:
datetime.datetime.fromtimestamp(float(x))),
])

def HandleEntity(self, entity):
event = datastore_entities.Event(entity.title)
event.update(entity)

creator = event['creator']
if creator:
contact = datastore.Query('Contact', {'title': creator}).Get(1)
if not contact:
contact = [datastore_entities.Contact(creator)]
datastore.Put(contact[0])
event['author'] = contact[0].key()

return event

if __name__ == '__main__':
bulkload.main(EventLoader())
"""

---
bulkload.Loader.__init__(self, 'Greeting',
[
('author', datastore_types.users.User ),
('content', str ),
('curl1', str ),
('cmapinfo', datastore_types.Text),
('date', lambda x: datetime.datetime.strptime(x,'%Y-%m-%d %H:%M:%S')),
('dateJST', lambda x: datetime.datetime.strptime(x,'%Y-%m-%d %H:%M:%S')),
])

--

C:\google\bulkload>c:\google\bulkload\bulkload_client.py --filename greeting_test.csv --kind Greeting --url http://xxxx.appspot.com/load02

2008年6月19日木曜日

model.properties()


kind =(Greeting(),Blog() )

for k in kind:

print "DROP TABLE IF EXISTS `" + k.kind() +"`;"
print "Create table `" + k.kind() + "` ("
print " `key` char(36) not null,"
print " `id` int,"
print " `key_name` char(12),"
p = k.properties()
for pp in p:
attr = str(p[pp]).split('google.appengine.ext.db.')[1]
attr = attr.split(' object')[0]
sql_attr = attr
if attr == "IntegerProperty" : sql_attr = "int"
if attr == "StringProperty" : sql_attr = "varchar(500)"
if attr == "ReferenceProperty" : sql_attr = "char(36)"
if attr == "DateTimeProperty" : sql_attr = "datetime"
if attr == "UserProperty" : sql_attr = "varchar(128)"
if attr == "TextProperty" : sql_attr = "text"
print "`" + pp + "`" + " " + sql_attr + ", #" + attr
print ") # remove last `,` !!!"

Local or Cloud

ようやく Cloud に 「Create and Application」できた。
しかし app.yaml の application: の部分を変更して、起動したことで
Local の datastore が初期化されてしまった。
バックアップがあるので、2,3日前の状態には戻せるが...
#!-*- coding:utf-8 -*-
import cgi
import wsgiref.handlers
import os

from google.appengine.ext import webapp
class MainPage(webapp.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'text/html'
self.response.out.write(u'Hello, webapp World! こんにちわ<br />' )
self.response.out.write(os.environ["PATH_INFO"] + "<br />")
self.response.out.write(os.environ["TZ"] + "<br />" )
self.response.out.write(os.environ["SERVER_NAME"] + "<br />")

-----
Hello, webapp World! こんにちわ
/hw0
UTC
localhost

2008年6月18日水曜日

「Google App Engine」の現況および今後の展開

http://codezine.jp/ の 【Google Developer Day 2008】 Google App Engineをおさらいしようより
500MBのストレージ、2GB/日のデータ転送量(500万PV/月 相当とのこと)まで無料
無償サービスについては、今後も継続していく予定
BigTableによる「分散型データストア」
SQLライクなGQLで操作できる。SQLのJOINにあたる機能はサポートしていないため、
少し慣れるのに時間がかかるが、分散環境の恩恵に預かれる。
確かに慣れるのに時間がかかると思う
現在、データベースAPIに含まれていない全文検索については、具体的な対応予定は
立っていない
SSLは今のところサポートしていないが、一部fetch APIなどではSSL接続を行っている
日本では、携帯電話のSMSによる認証関係のバグで試すことができないようだ(6月11日現在)。
これについてGoogleは、おそらく今週から日本でも使えるようになるはずだ
おかげさまでようやく Sign Up することができました。

2008年6月17日火曜日

Datastore Viewer Error

key ="agpoZWxsb3dvcmxkcgsLEgRCbG9nGPckDA"
r = db.get(key)
is OK.

But...
Google\google_appengine\google\appengine\ext\admin\__init__.py", line 542, in input_field
if len(sample_value) > 255 or sample_value.find('\n') >= 0:
TypeError: object of type 'NoneType' has no len()

Odd behaviour in admin interface
http://groups.google.com/group/google-appengine/browse_thread/thread/29cd28daea3c37d3?fwc=1

2008年6月16日月曜日

alter table ...

TextProperty は検索に利用できないのでStringPropertyに変更しようと、
db.Model を修正し、
None で Update
したが、新たに Text データを put したところ、また
TextProperty として表示されてしまった。

それで、
新しい、StringPropertyを追加したが、反映されるタイミングがまだわからない。
すくなくとも新しい Property に No error で put できても、実際には
データどころか、 Property さえ、作成されていなかったりする。

Propertyを追加した場合は、必ず
http://localhost:8080/_ah/admin/datastore/
で確認し、ここで追加部分に値を登録してみておいたほうがよい。

更新処理は時間がかかるので、これが無駄になると、時間の無駄。



class TextProperty()

A long string.
Unlike StringProperty, a TextProperty value can be more than 500 bytes long. However, TextProperty values are not indexed, and cannot be used in filters or sort orders.

Swift UI チュートリアル Loading watchOS が終わらない?

Loading watchOS が終わらない? ディスク容量の残量が少ないので不要なシュミレーターを削除したとこころ watchOSのものが全部なくなってしまっていた。 WatchOS を削除して再度インストールしても復活せず。 Create a new simulator で ...