ラベル GAE Python の投稿を表示しています。 すべての投稿を表示
ラベル GAE Python の投稿を表示しています。 すべての投稿を表示

2011年2月17日木曜日

GoogleAppEngine index.yaml 設定

日々躓くことが多すぎます。

もう少し難しいところで躓けばいいのですが。

いつも基本的なところで躓くので一向に進んでいきません。。。

今回はindex.yamlについて調査。

各Kind情報に対してindexを定義するファイルとのこと。

ファイルの中身は下記。

----------------------------------------

indexes:


# AUTOGENERATED


# This index.yaml is automatically updated whenever the dev_appserver
# detects that a new type of query is run.  If you want to manage the
# index.yaml file manually, remove the above marker line (the line
# saying "# AUTOGENERATED").  If you want to manage some indexes
# manually, move them above the marker line.  The index.yaml file is
# automatically uploaded to the admin console when you next deploy
# your application using appcfg.py.


- kind: City
  properties:
  - name: area
  - name: prefecture



----------------------------------------


# AUTOGENERATED←これを入れておけばfilter、sortで使用している項目に対して、

indexを自動で定義してくれる。※複数項目を条件で指定した場合のみ。

逆にindexを定義しないとエラーで落ちてしまうので、自動生成にしておくと便利。

しかしながら不要になったindexは自動では削除されないようで。(それは当然か。)

不要なindexは削除しておかないとサーバーのリソースも食ってしまうので、開発段階では定期的にメンテナンスの必要あり。


実際は、BigTableの仕組みをまだあまり理解していないので、そこから勉強しないとだめかなと。

今回、複数項目に対して検索をするとindexが生成されると認識していただのですが、ReferencePropertyの項目のみ使用するとindexは生成されないみたいで。

イメージ的にはKeyになっている項目なので必要はないのかと。

ただ普段よく利用している、リレーショナルDBとはかなり感覚が違う気がするので。

物覚えが悪い自分としてはまた一つ壁です。

引き続き要勉強!

わからないことが多すぎて。

日々精進。

2011年1月30日日曜日

Python CSVデータ 一括登録 bulkloader編

以前に書いたブログ。
Python CSVデータ 一括登録 TaskQueue編

なんだけど今回別の方法があると、こっちのほうが効率がいいのではと。

というかこっちを使うのが一般的ではないかと。

なので検証することに。

いろいろ検索するとたくさんの方が記載していました。Google本家も参考に。
Google App Engine データのアップロードとダウンロード
bulkloader.py を使って Google App Engine の本番サーバーから開発サーバーにデータを移す
他多数。

ただ今回実際にやってみて、整理するためにも書いときます。

まず、remote_apiの設定。app.yamlにて簡単に設定できます。

次に一括登録のために必要な登録するデータ(今回はCSV)とKindのPropertyとをマッピングすることが必要。

そのために下記ファイルを使用する。
bulkloader.yaml


自動生成が簡単にできます。もちろん生成後は多少編集が必要ですが。

下記コマンド。
C:\> appcfg.py create_bulkloader_config --filename=bulkloader.yaml --url=http://example.appspot.com/remote_api
実行結果。
Creating bulkloader configuration.
[INFO    ] Logging to bulkloader-log-20110129.101716
[INFO    ] Throttling transfers:
[INFO    ] Bandwidth: 250000 bytes/second
[INFO    ] HTTP connections: 8/second
[INFO    ] Entities inserted/fetched/modified: 20/second
[INFO    ] Batch Size: 10
[INFO    ] Opening database: bulkloader-progress-20110129.101716.sql3
[INFO    ] Opening database: bulkloader-results-20110129.101716.sql3
[INFO    ] Connecting to biyotest.appspot.com/remote_api
[INFO    ] Downloading kinds: ['__Stat_PropertyType_PropertyName_Kind__']
.[INFO    ] __Stat_PropertyType_PropertyName_Kind__: No descending index on __ke
y__, performing serial download
.........................................................
[INFO    ] Have 573 entities, 0 previously transferred
[INFO    ] 573 entities (223932 bytes) transferred in 78.1 seconds


これで取得完了。


yamlの中身は下記。

# Autogenerated bulkloader.yaml file.
# You must edit this file before using it. TODO: Remove this line when done.
# At a minimum address the items marked with TODO:
#  * Fill in connector and connector_options
#  * Review the property_map.
#    - Ensure the 'external_name' matches the name of your CSV column,
#      XML tag, etc.
#    - Check that __key__ property is what you want. Its value will become
#      the key name on import, and on export the value will be the Key
#      object.  If you would like automatic key generation on import and
#      omitting the key on export, you can remove the entire __key__
#      property from the property map.
# If you have module(s) with your model classes, add them here. Also
# change the kind properties to model_class.
python_preamble:
- import: base64
- import: re
- import: google.appengine.ext.bulkload.transform
- import: google.appengine.ext.bulkload.bulkloader_wizard
- import: google.appengine.ext.db
- import: google.appengine.api.datastore
- import: google.appengine.api.users

transformers:

- kind: Kind1
  connector: # TODO: Choose a connector here: csv, simplexml, etc...
  connector_options:
    # TODO: Add connector options here--these are specific to each connector.
  property_map:
    - property: __key__
      external_name: key
      export_transform: transform.key_id_or_name_as_string

    - property: password
      external_name: password
      # Type: String Stats: 1 properties of this type in this kind.

    - property: user
      external_name: user
      # Type: String Stats: 1 properties of this type in this kind.

データストアのKindの情報をダウンロードできる。



なので更新したいKindの #TODO~ となっている箇所を編集。



今回はCSVを使用する。
connector:csv

下記は設定しなくても良い。どんな場合に使うかはまだ不明。
connector_options: ← 削除
external_nameを編集する。


今回の場合はcsvを使用するので先頭行ににて使用している該当の項目名を設定する。


reference_propertyはreference_classを設定。
- property: user
      external_name: user
      # Type: Key Stats: 1286 properties of this type in this kind.
      import_transform: transform.create_foreign_key('User') reference_classを設定
      export_transform: transform.key_id_or_name_as_string
編集終了後データをアップロード。


下記コマンド。
C:\>appcfg.py upload_data --config_file=bulkloader.yaml --filename=example_data.csv
 --kind=Kind1 --url=http://example.appspot.com/remote_api
実行結果。
Uploading data records.
[INFO    ] Logging to bulkloader-log-20110129.151144
[INFO    ] Throttling transfers:
[INFO    ] Bandwidth: 250000 bytes/second
[INFO    ] HTTP connections: 8/second
[INFO    ] Entities inserted/fetched/modified: 20/second
[INFO    ] Batch Size: 10
[INFO    ] Opening database: bulkloader-progress-20110129.151144.sql3
[INFO    ] Connecting to biyotest.appspot.com/remote_api
[INFO    ] Starting import; maximum 10 entities per post
................................................................................
.................................................
[INFO    ] 1286 entites total, 0 previously transferred
[INFO    ] 1286 entities (3600417 bytes) transferred in 65.6 seconds
[INFO    ] All entities successfully transferred
これで一括登録完了。


気づき。

・blobpropertyは使用不可。
→登録できなかった。調べてみると方法があるみたいだけど、それでもうまくいかず。要調査。


・listpropertyは登録は完了するが、不正な値で登録されてしまう。
→こちらはサポート外?要調査


・下記propertyは登録しない。
 - property:_key_
 - property:_scatter_

→_key_は自動載番される。
→_scatter_はどのように使われているかは不明。


今回使用してみて、GAEのサーバーリソース軽減になるかと試してみたが、ほとんど一件一件登録する場合と変わらず。


ただ時間はかなりはやいので時間のメリットはあるかと。


リソースの使用量が同じぐらいならこちらを使うメリットはあるかなというところですね。


まあ細かいところはまだまだ勉強不足。


わからないことが多すぎて。


日々精進。


2011年1月7日金曜日

Python CSVデータ 一括登録 TaskQueue編

WEBサイト構築中につき大量のデータを登録することに。

大体数万件になりますか。

今回GAE+Pythonで開発中。

CSVファイルのアップロード機能を裏ページに実装し、登録を試みるが、

GAEの1リクエスト30秒という制約により一回に約200件ずつしか登録できない。

数万件のCSVファイルを数百件毎に分割するのも面倒、というか膨大な時間がもったいない。

そこで、登録処理を自動かつ大量に一括で走らせるために試行錯誤中。

今回はTask Queueをデータ登録用に作成。

一件ずつTaskを登録し、定期的に処理を実行することで自動化を実現することに。

肝心なCSVデータは一時的なものなので、GAEとは別の公開用のサーバーにアップ。

pythonライブラリ urllibを使用しCSVデータにアクセスした。

tasks.py
----------------------------------------------------------------------

#!/usr/bin/env python
# -*- coding: utf-8 -*-


from google.appengine.ext import webapp
from google.appengine.api.labs import taskqueue
import urllib


class add_tasks(webapp.RequestHandler):
  def get(self):

    mytask = taskqueue.Queue('task-queue')
  
    #URLパス
    urlRequest="http://example.com/csvdata/data.csv"
    #CSVファイルにアクセス
    result = urllib.urlopen(urlRequest)
  
    #取得したデータを1行ずつTaskに追加
    for readline in result.readlines():
        row = readline.split(',')
        if len(row) > 0:
            task = taskqueue.Task(url='/data_ins' , params = {
                                                              'prm0':unicode(row[0], 'cp932'),
                                                              'prm1':unicode(row[1], 'cp932'),
                                                              'prm2':unicode(row[2], 'cp932'),
                                                              'prm3':unicode(row[3], 'cp932'),
                                                              })
            mytask.add(task)
----------------------------------------------------------------------

これだけのことなのにまたかなりの時間を要しちゃいました。

ただこの後、実際にTaskの実行で走らせる登録処理が動作せず。

簡単に直せそうだったけどまたはまっちゃいそうだし、力つきてTaskの登録までで終了。

pythonが全然慣れません!

わからないことが多すぎて。

日々精進。