Hatena::ブログ(Diary)

Rails etc... Memo

2015-03-02

[]ndbのquery結果の件数を取得する方法

自分の中でごっちゃになっていたので整理する。

Queryのcount()のリファレンスには、こうある。

This returns the same result as len(q.fetch(limit)) but more efficiently.

query = MyModel.query(条件)
cnt = query.count() #OK
cnt = len(query)    #NG
cnt = len(query.fetch()) #OK

list = MyModel.query(条件).fetch(keys_only=True)
cnt = list.count() #NG
cnt = len(list) #OK

queryメソッド戻り値(Queryオブジェクト)はイテレータではあるがリストではないので、len(query)はできない。

fetchメソッド戻り値は単なるリストなので、

last_data = list[cnt-1]

みたいなことも出来る。

2015-02-27

[]ローカル開発サーバ起動時に import docker でエラーが発生するようになった(2015/02/26時点)

つい今しがた、1ヶ月ぶりぐらいに、gcloud components update をやったら、ローカル開発サーバが起動しなくなってしまった。

エラーログ

			
Running dev_appserver with the following flags:
--skip_sdk_update_check=yes --port=12080 --admin_port=8004 --log_level=debug --datastore_path=/Users/noazoh/develop/app_id/datastore/dev_appserver.datastore Python command: /usr/bin/python2.7 Traceback (most recent call last): File "/Users/noazoh/google-cloud-sdk/platform/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/dev_appserver.py", line 83, in <module> _run_file(__file__, globals()) File "/Users/noazoh/google-cloud-sdk/platform/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/dev_appserver.py", line 79, in _run_file execfile(_PATHS.script_file(script_name), globals_) File "/Users/noazoh/google-cloud-sdk/platform/google_appengine/google/appengine/tools/devappserver2/devappserver2.py", line 36, in <module> from google.appengine.tools.devappserver2 import dispatcher File "/Users/noazoh/google-cloud-sdk/platform/google_appengine/google/appengine/tools/devappserver2/dispatcher.py", line 29, in <module> from google.appengine.tools.devappserver2 import module File "/Users/noazoh/google-cloud-sdk/platform/google_appengine/google/appengine/tools/devappserver2/module.py", line 71, in <module> from google.appengine.tools.devappserver2 import vm_runtime_factory File "/Users/noazoh/google-cloud-sdk/platform/google_appengine/google/appengine/tools/devappserver2/vm_runtime_factory.py", line 25, in <module> from google.appengine.tools.devappserver2 import vm_runtime_proxy File "/Users/noazoh/google-cloud-sdk/platform/google_appengine/google/appengine/tools/devappserver2/vm_runtime_proxy.py", line 29, in <module> from google.appengine.tools.devappserver2 import log_manager File "/Users/noazoh/google-cloud-sdk/platform/google_appengine/google/appengine/tools/devappserver2/log_manager.py", line 34, in <module> from google.appengine.tools.docker import containers File "/Users/noazoh/google-cloud-sdk/platform/google_appengine/google/appengine/tools/docker/containers.py", line 47, in <module> import docker ImportError: No module named docker

dockerがimportできないよ、と言っている。

dockerが何かわからなかったので軽く調べたところ、最近betaとして公開された、Managed VMs に関連するもののようだ。

dockerインストールされている事を前提としてしまっているようだ。

いつか修正されるような気はするのだが、とりあえず動くようにするためには、dockerインストールする必要がある。

sudo easy_install pip

でpipをインストールしてから、

sudo pip install docker-py

dockerインストールすることにより、エラーが解消しました。

Managed VM の機能を使わないのだから(app.yaml にて、vm: true にはしていない)、dockerをimportしないようにするとか何かしてほしい。

2015-02-19

[]ローカル開発サーバでCronJobのテストをする際の注意点

cron:
- description: test job
  url: /hoge
  schedule: every day 18:00
  timezone: Asia/Tokyo
  target: rev01

という感じでタイムゾーンを指定しても、ローカル開発サーバではタイムゾーンを考慮してくれません。

[]cron.yaml における target の意味

targetに指定するものは、app.yaml における version です。

サーバにリリースはしたが、デフォルトは別のバージョンにしている、などの時に使うもの。

2015-02-06

[][]ndbでDISTINCTなSELECTをするには

DISTINCTのやり方

import pprint

from google.appengine.ext import ndb
from src.models import my_model  #というモジュールがあるとして

query = my_model.MyClass.query(
    projection=[ 
        my_model.MyClass.property1, 
        my_model.MyClass.property2
    ],
    distinct=True)

projectionで射影

distinctで集約

2015-02-04

[]デプロイ時のアプリケーションIDの指定について

アプリケーションIDを、仮に、APP_ID とする。

app.yaml
application: APP_ID

で、これをローカル開発サーバで実行させると、アプリケーションIDは、

dev~APP_ID

となる。これはどこでわかるかというと、ローカル開発サーバの管理コンソール(http://localhost:管理用ポート番号/instances)を開くと表示されているもので、例えば、bulkloaderなんかで、ローカル開発サーバアプリケーションIDを指定するときなどにも使用するものだ(参考:http://road2win.plala.jp/wordpress/?p=6427)。

で、このアプリケーションIDであるが、チュートリアルなどを見ていると、たいていの場合、サーバ側のプロジェクトIDと、app.yamlで指定する "application:"の値と、appcfg.pyなどで指定する -A オプションの値がすべて同じ、という例が多いため、区別がつきにくいのだが、-Aオプションの値はサーバ側のプロジェクトIDと同値を指定しなくてはいけないが、app.yamlには、それとは異なる値を設定することができる。

例えば自分の場合、1つのアプリケーションに対して、ステージング用サーバと本番サーバの2つを用意することが多いので、1つのソースコードを、2つのサーバ(プロジェクト)に向けてデプロイしている。

アプリケーションIDが "hogeapp" 、ステージング用のプロジェクトIDが "hogeapp_s"、本番用プロジェクトIDが "hogeapp_r" だとすると、

app.yaml
application: hogeapp
ステージングへのデプロイコマンド
appcfg.py -A hogeapp_s update ディレクトリ名 …
本番へのデプロイコマンド
appcfg.py -A hogeapp_r update ディレクトリ名…

とする。app.yaml をいちいち書き換える必要はない。

Googleアカウントとの関係

上記のデプロイコマンドの例では、Googleアカウントを指定していない(--emailオプションを指定してない)。その場合、gcloud auth list コマンドで"active"と表示されるアカウントデプロイを実行しようとする。

このとき、hogeapp_s や、hogeapp_r に、そのアカウントに対する権限が設定されていないと、

Error 404: --- begin server output ---
This application does not exist (app_id=u'hogeapp_r').
--- end server output ---

というエラーが発生してデプロイに失敗する。

自分の場合、認証や権限等の機能のテストのため、2つ以上のGoogleアカウントを使い回して開発することが多い。gcloud auth コマンドで、アクティブアカウントを切り替えることができるが、この切り替えを失念したまま、--emailオプションもつけずにデプロイしてエラーが出て「スペルミスか?」と悩む、ということを何度か繰り返してしまった。

appcfg.py update の際は、常に --emailオプションを付けるクセをつけるべきだろう。