「プログラム」カテゴリーアーカイブ

Google app engineのCRONで月に1回だけ動かす

Google app engineのpythonで、月に1回だけ動かす方法。
何分ごと、毎日何時、毎週何曜と何曜の何時、毎日何時から何時の間に何分ごと
これらはわかったけども、月に1回だけがわからなかった。

結局、月に1回は以下でOK

15 of month 05:00

これだと、毎月15日の5時に動かすとなる。管理画面でチェックすると、CRONの起動予定の日時が表示されるので、ここで正しいか確認できる。

GAE(appengine)のパフォーマンス設定でスライドバーが2つずつ出てきた

グーグルのGAE(appengine)のアプリケーション設定画面でパフォーマンスを設定するスライドバーが2つあるんだけど、そこにある調整用のスライドが各バー1個から2個に増えていた。意味がわからないのでしょうがなく英語のマニュアルを見てみると、これは課金設定をONにした場合のみ出現するらしい。そういえば、この前課金設定をONにした気がする・・。

で調べたところ。

Idle Instancesのバー設定は、
上のバーが最小インスタンス数、下のバーが最大インスタンス数を設定する。1つのインスタンスで1つの仕事をするので、同時に何十個立ち上げると並列でいろんなことができるけど、料金は高くなるという仕組みらしい。最小インスタンス数を調整すると常にインスタンスが動いていることになるので、この設定は課金してないと出来ないという理由がわかった。できるだけコストを下げるには、上のバーはAutomatic、下のバーは1に設定する。これだと最大でもインスタンスは1しか動かず必要ないときには0になる。最小を1に設定してしまうと常に1個立ち上がった状態になる。

Pending Latencyのバー設定は、上の下の違いがよくわからず
とりあえず、Pending Latencyというのは、インスタンスに空きがない時に、どのくらいの時間待つと、新しいインスタンスを立ち上げるか?の設定で下のバーはその待ち時間の最大を設定。なので、最大の15sにすると一番コストは低くなるはず。15sとAutomaticがすぐ近くにあるからなにか変な感じがするがたぶんこの理解であっているはず・・・。上のバーも時間を長くするほどコストは下がるようなので、

結局設定は

Pending Latency: ( 15.0s – 15.0s )

とした。まだイマイチ使い方がわかっていないので、無料期間(最初300ドル分の無料クーポンを貰えた)の間にいろいろ試しておこう。

GAE pythonでのランダムな「AttributeError: ‘~’ object has no attribute ‘~’」の原因

GoogleAppEngine(GAE)のpythonでハマったのでメモ。
具体的には以下のエラーが出た。

AttributeError: ‘~’ object has no attribute ‘=’

~のところには、自分で設定した名前が入る。
このエラーが出るだけなら、単純なんだけど、名前の間違いとか、データが入っていないとかは無くて、それでもなぜかエラーが出たり出なかったりする。この出たり出なかったりという反応の仕方をするので解決に時間がかかった。完璧に100%エラーが出るなら原因は特定しやすいんだけど。

具体的には以下の様な使い方をしていた。

class datax(ndb.Model):
cat = ndb.IntegerProperty()

まず上の用に設定して、以下のようにデータを取り出す。

q = datax.query()
qry2 = q.filter(~)
qry3 = qry2.order(-~)
qry4 = qry3.fetch(1)
datay = qry4[0].cat

~の部分は省略。
この時に、上記のAttributeErrorが出たり出なかったりした。いろいろ試して最後やっと解決したけど、原因は

class datax(ndb.Model):
cat = ndb.IntegerProperty()

の部分だった。class datax(ndb.Model)というのは実際には、

class datax(ndb.Model):
cat = ndb.IntegerProperty()
dog = ndb.IntegerProperty()
bird = ndb.IntegerProperty()
frog = ndb.IntegerProperty()

なんだけど、このファイル内で使うのは、

cat = ndb.IntegerProperty()

だけだったから、

class datax(ndb.Model):
cat = ndb.IntegerProperty()

ファイル内をスッキリさせるために、上記のように使うものだけ入れて書いていた。最初試しに省略したら、普通に問題なく動いたので、これでいいんだと思い込んでいた。で、上記の部分を全ファイル省略せずに書くようにしたら、エラーが完璧に0になった。どういう仕組でエラーが出たり出なかったりしていたのかはわからないけどもとりあえず解決して良かった。

Google App EngineのデータベースNDBのProperty Optionsについて。

Google App Engineのpythonでデータを出し入れするときには、NDBというデータベースをMYSQLの代わりに使う。
NDBのProperty(データ)にはオプション設定がいろいろ用意してあるんだけど、今までオプション設定の必要性を感じたことがなかった。
ところが、NDBからデータを利用するときに、エラーが出ることがあって、エラーを避けるために、データを取り出すときではなくて、入れる段階で処理すると楽だなと思い、そういえばオプション設定があったな、と思い出し、グーグルのマニュアルを見てみると便利そうなものがたくさん用意されていた。

ndb.IntegerProperty(required=True)

みたいに、requiredを設定すると、値が必ず入っていないとダメなので、取り出す時にデータが入ってなくてエラーが出るということを避けられる。ということがやっとわかった。

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()が完了するまで待ってくれる、ということらしい。