PythonのNDB Asynchronous(非同期)での@ndb.toplevelの使い方

Google App EngineでNDB Asynchronousを使うときに@ndb.toplevelというのが出てきた。

class MyRequestHandler(webapp2.RequestHandler):
@ndb.toplevel
def get(self):
acct = Account.get_by_id(users.get_current_user().user_id())
acct.view_counter += 1
acct.put_async() # Ignoring the Future this returns
# …read something else from Datastore…
template.render(…)

マニュアルのサンプルコードがこれで、最初は何のことかチンプンカンプンだった。
一晩寝て次の日になってやっとわかってきて
async()は、複数のことを同時にできるから、例えば、100個の命令を同時に出して、まだ全部の命令が完了していないのに
次の命令、サンプルだとtemplate.render(…)が実行されてしまうと、async()のまだ終わってないのに、次の段階に進んでしまい永遠に
async()の内容が完了しないままになることがあるかもしれない。そこで登場するのが@ndb.toplevelで、これをつけると、async()が完了するまで待ってくれる、ということらしい。

Google Cloud StorageにPythonでデータのやり取りをする

何をしたいかというと、GCS(Google Cloud Storage)にプログラムでデータを放り込んだり取り出したりしたい。

最初は、Blobstoreという物を使おうと思い調べていたけど、グーグルのマニュアルに、プログラムでBlobstoreへ書き込む機能はもうじきなくなるので、GCS(Google Cloud Storage)の方をおすすめする、みたいなことが書いてあったので、GCSの方を使うことにした。

使うのはpythonで、GCS(Google Cloud Storage)とやりとりするためには、Google Cloud Storage Python Client Libraryというのを使う必要があるらしく、まずはこのファイルをダウンロードしてインストール。インストールと言っても、、そのライブラリーのcloudstorageというフォルダがあれば、それをアプリと同じフォルダ(最初階層を間違えてエラーが出た)に置くだけで使えるようになった。

あとは、

import cloudstorage as gcs

でライブラリーを読み込んで、

g_file = gcs.open(filename,’w’,content_type=”,retry_params=write_retry_params)
g_file.write(testfile)
g_file.close()

とするだけでOKだった、予想以上に簡単。
filenameは固有のbucketの後は自分で好きに決めれてサブディレクトリみたいに、表面上は/a/b/c/catと整理しやすくできるみたい。
testfileに書き込む内容を入れる。
‘w’は書き込みモードで読み込むときはrにする。content_typeは自由に決めれることができるので書き込むファイルに合わせる。retry_paramsは良くわからないけど、書き込みに失敗した時に、どういう対応をするのか決めるっぽい。

次に、writeで書き込んで、closeで終わり。

書き込んだファイルを読み込む場合は、固有のbucketの後に、自分で決めたファイル名をつなげたURLにアクセスすると表示できる。
ブラウザで操作できるディベロッパーコンソールから書き込んだファイルの確認や削除、一般公開のON,OFFの設定や公開するときのURLの確認等もできた。

ImportError: No module named cloudstorageというエラーが出てしまう場合の解決方法

Google App EngineのpythonでGoogle Cloud Storage Client Libraryを試しに使おうと思い、グーグルのマニュアルを読んでいたんだけど、
デモのファイルを動かすときに以下のエラーが出てはまった・・・
インストールはPyPi(PyPiは何のことか知らなけど、以前にも使ったことがあった)を使い、マニュアル通りに

pip install GoogleAppEngineCloudStorageClient -t <your_app_directory/lib>

とした。これは、your_app_directoryのとこに自分のアプリ(appangineの本体ではなくアプリのファイル)のアドレスをそのまま置き換えて、コマンドプロンプトでコピペするだけでOKだった。

ところが、

ImportError: No module named cloudstorage

というエラーが出て、いろいろ試行錯誤しても駄目で、
海外のサイトを見ると、

import lib/cloudstorage as gcs

のようにlib/をつけると上手く行ったと書いてる人もいたが、上手く行かず
結局どうしたら解決したかというと、
アプリのlibフォルダの中にcloudstorageというフォルダがあるから、これをlibファオルダから出して、一つ上の階層にあげて
app.yamlとかサンプルファイルがある場所に移したらあっさり解決した。

ちなみにPyPiでインストールすると、サンプルファイルが含まれてないようだけど、マニュアルにあるサンプルソースをコピペして、ファイル名の場所だけ変えればそのまま使えた。

Google Cloud Storage Pythonを使ってみる

グーグルがやってるクラウドサービスというのを試しに使って見てるが、まだ良くわからないところが多い。

基本の単語からわからなくて、取り敢えず、データを収める場所がバケットで、収めるデータをオブジェクトというらしい。

面白いなと思ったのは、サブディレクトリの仕組みで
例えば、
animal/sea/fish
というサブディレクトリの構造らしきものがあったとして(これをバケットというらしい)、実際は、animalの下にseaフォルダがあって、そこにfishというファイルがあるんではなくて
たんに、fishというファイルにanimal/sea/fishという名前が付いているだけということらしい。

グーグルのクラウドサービスを見るとなんでも用意されてるので、ほんとできるだけ自前でやらずに用意されているものを上手に組み合わせてどう利用するかが大切だなぁと思った。

GAE(Google App Engine)pythonのNDBでデータの有る無しを確認してから取り出す。

GAEのデータストアNDBからデータを取り出す時にはまった。
日付データと、いくつかの文字列型のデータを収めるデータ型のクラスがあって、文字列は時々からの場合がある。
これをデータが空でないエンティティだけを取り出して、日付データでソートする、というのをやりたかったんだけど、どうしてもエラーが出てしまう。
どうも、このデータ型のクラスだけでは、希望のデータ取り出し方法はできないようで、結局、もう一つBooleanProperty型のプロパティを加えてあげることで解決した。

BooleanPropertyはTrueかFalseを収めることができる型で、データを入れるときにデータがあれば、BooleanPropertyをTrueにしておく。すると、取り出すときに、BooleanPropertyがTrueの物をフィルタリングすることで、あっけなく希望通りのデータ取り出しが出来た。