Python :

BeBop β version


先日Cloque.内で進めているデバッグサービス、BeBopがβ版になりました!今日はBeBopの新機能とか今後の展開について考えてる事をメモ。

新機能
今回のアップデートの目玉はユーザーとプロジェクトの管理です。
この機能により、ユーザーは自分のプロジェクトを設定できるようになりました。バグリポートはプロジェクトごとに振り分けて報告できるので、複数のプロジェクトが同時進行してても混乱しません。また、プロジェクトごとに共有ユーザーを設定できるので、クライアントの担当者や、他社の共同開発社と共有が可能になりました。

その他、検索項目の追加やバグリポートのステータス管理などが可能になりました。今の所、ステータスの変更はプロジェクト管理者しか行えません。(要望があれば変更するかも)


今後の展開
前回のバージョンではProgressionの使用が前提になっていましたが、今回から非Progression環境でも動作します。もちろんProgressionが使用されている場合は、Progression特有の情報を利用できます。この変更を優先した背景にはFlashの活動領域の変化があります。今後の同行次第ではひょっとするとフィーチャーフォン向けにAS2版も出す事になるかもしれません。

また、次期バージョンまでの最優先事項はAndroid(ADK)アプリへの対応です。iOSに関してはもう少し後になりそうです。現状では「Androidからのバグリポートで必要なものは何か?」をAndroidアプリの開発を行いながら見極めています。


今一度、BeBopって?
BeBop開発の発端は、クライアントからの「XXのページに行って、OOのボタン押して、$$のページ行こうとして、やっぱ¥¥のページ行ったらフリーズした」的なバグリポートをもうちょっと詳細に把握できないかな〜という思いつきです。クライアントにスクリーンキャプチャを取ってもらったり、OSやFlashの詳細なバージョンを聞き出すのは以外に手間がかかります。
今後のスマートフォンによるマルチスクリーン・マルチデバイス環境の到来により、この傾向はさらに拍車がかかるだろうと思ってます。

イマイチ、何が出来て何がオトクなのか伝えるのが難しいツールですが、最後にSiONの@keim_at_siさんが『超高機能な「問題を報告するボタン」』と見事にまとめてくれた言葉で締めたいと思います。

[お詫びと訂正]結合したQueryへのfetch()的アクセス

前回のエントリーでqueryをitertools.chain()してitertools.islice()すると複数のqueryを結合してfetch()できるよ。と書きましたが、その後の検証で非常に非効率な処理が走る事が判明したので訂正します。
具体的にはitertools.islice()でイテレーターをスキップさせると内部的にはスキップさせた分だけnext()が走るみたいです。
つまり
islice('ABCDEFG', 2, 4) 
はC、Dを返すのですが、A、Bに関して戻り値に含まれないだけで内部では走査されちゃうようです。

例えば
q1 = HogeModel.all().filter("name =", "Spike Spigel")
q2 = HogeModel.all().filter("name =", "Jet Black")
q3 = HogeModel.all().filter("name =", "Faye Valentine")
qchain = chain(q1,q2,q3)    

 #1000番から1020番のQuery結果を得る
islice(qchain,1000,1020)
を実行した場合、queryが1000回、next()を実行する事になります。 という訳でこの方法はトンでもないバッドノウハウだったので、この場を借りて深くお詫びいたします。

ちなみに余談ですが、
q1 = HogeModel.all().filter("name =", "Spike Spigel")
q1[1000:1020]
と実行した場合はfetch()が走り、next()をぶん回す事は無いようです。

結合したQueryへのfetch()的アクセス

[ご注意!]
以下のエントリーは、状況により大きく負荷がかかる場合があります。詳しくはこちらをお読みください

前回のエントリーでBigtableから複数のQueryを結合する方法を紹介ました。 この方法は非常に便利ですが、chain()メソッドにより結合したQueryはitertools.chainオブジェクトに変換されてしまうのでQuery固有のメソッドが使えません。

うっかりfetch()とかcount()を実行すると
AttributeError: 'itertools.chain' object has no attribute 'count'
とお叱りを受けます。

特にfetch()が使えないのは致命的に思えます。 例えば1000件の検索結果の中から200番から210番だけ取り出したい場合に途方に暮れるじゃないですか。

で、ここでキラーメソッドの登場です。 itertools.islice()メソッドです。

islice('ABCDEFG', 2, 4) 
と実行するとC,Dを返すイテレータを生成してくれます。 Queryに対して使う場合はこんな感じです。
q1 = HogeModel.all().filter("name =", "Spike Spigel")
q2 = HogeModel.all().filter("name =", "Jet Black")
q3 = HogeModel.all().filter("name =", "Faye Valentine")
qchain = chain(q1,q2,q3)    

 #10番から20番のQuery結果を得る
islice(qchain,10,20)
これにより実質的にfetch()メソッドが利用可能となり、万々歳なわけですが、ホントにitertoolsはスゲー奴ですね。

ちなみにitertoolsのソースコードを見てやろうと/System/Library/Frameworks/Python.framework/Versions/ の中を探してみたけど見つかりませんでした。いけずな奴です。

ActionScriptにはビルトインなイテレータが存在しないし、 実際のコーディングでもワザワザ定義して使う事は稀だと思います。 最近、周囲のFlasherさんたちがGAE/Pyに参入し始めていますが、僕のようにイテレータに不慣れな人も結構多いんじゃないのかと思ったりする今日この頃でした。

次回は実際にchain()、islice()を使って複数Queryの検索結果をPagenateさせてみたいと思います。

GAEのBigtableから複数の検索結果を取得してみる

例えば下記のようなエンティティがあるとして..

nameage
Spike Spigel0
Jet Black1
Faye Valentine2
Spike Spigel3
Jet Black0
Faye Valentine1
Spike Spigel2
Jet Black3
Faye Valentine0
Spike Spigel1

ここから
ageが2以上の"Spike Spigel"、
ageが3以上の"Jet Black"、
aqeが2の"Faye Valentine"
を検索し列挙したい場合、上記3つのクエリを実行し、結果を結合する。

具体的なコードはこんな感じになる
a1 = Accounts.all().filter("name =", "Spike Spigel").filter("age >=", 2)
a2 = Accounts.all().filter("name =", "Jet Black").filter("age >=", 3)
a3 = Accounts.all().filter("name =", "Faye Valentine").filter("age ==", 2)
ac = chain(a1,a2,a3)    
結合しておけばその後のループ処理などで何かと便利。(特にページングが発生する場合など)
for a in ac:
    self.response.out.write(a.name+" age"+str(a.age))
    self.response.out.write("
")
念のため付け加えると、
a1 = Accounts.all().filter("name =", "Spike Spigel").filter("age >=", 2)
a1.filter("name =", "Jet Black").filter("age >=", 3)
a1.filter("name =", "Faye Valentine").filter("age ==", 2)
と処理した場合は絞り込み検索になってしまうので、期待する結果は得られない。

MySQLならSQL文で「OR」を使えばOKのはず。
しかしGAEのGQL及びQueryにはそういった機能は無さげなので個別に検索した後、結合しなければならない。
もしかするともっとエレガントな方法があるかもしれないので、ご存知の方がいらっしゃったら是非教えてください。

[ソースをDownload]

[追記]
イテレータの結合は標準ライブラリで可能です。
こちらのページが参考になりますよ。
itertools - 効率的なループ処理のためのイテレータ関数

http://www.python.jp/doc/release/library/itertools.html#itertools.chain

Pythonについて知っている2,3の事柄-AS3との比較-

先月はPythonでのコーディングをたしなんだので、AS3と比較しながらPythonメモ。

インデント

Python
def hoge():
    print "hoge"
AS3
function hoge():void{
    trace("hoge");
}

Pythonと言えばインデント。コードブロックはインデントで表現する。コーディングの一貫性を狙っての事だと思うけど、Pythonみたいなシンプルな文法だから可能なんだろう。AS3なんてコンストラクタ書く時点でインデントが二つも付いて、あれよあれよとコードが右へ寄ってくからね。


変数定義

Python
myname = "kappalab"
AS3
var myname:String = "kappalab";

"var"や型指定がいらない。AS1みたいな感じかな。


関数定義

Python
def hoge(value="hoge",*arg):
    for i in arg:
        print i
        
    print "hoge"
AS3
function hoge(value:String="hoge",...arg):void{
    for each(var i:* in arg){
        trace(i);
    }
    trace("hoge");
}

Pythonだと宣言は"def"を使う。こちらも型指定いらず。引数のデフォルト値の指定は同様。


クラス定義

Python
class Hoge (object):
    def __init__(self):
        self.name  = "kappalab"
        print self.foo()
        
    def foo(self):
        return  "Hoge:foo"
AS3
package{
    public class Hoge extends SuperHoge{
        public var name:String;
        public function Hoge():void{
            name = "kappalab";
            trace(foo());
        }
        public function foo():String{
            return "Hoge:foo";
        }
    }
}

Pythonだとコンストラクタは"__init__"で定義する。でもって第一引数に"self"を渡す。また、インスタンスメソッドの第一引数にも必ず"self"を渡す。さらにインスタンス変数(プロパティと言うとAS3とちょっと意味合いが異なるみたい)及びインスタンスメソッドを参照するときも"self.name"とする。AS3の"this.name"とよく似ているが、AS3が"this"を省略可能なのに対してPythonは必須。

そして、変数は全てコンストラクタ内で定義。AS3みたいにあらかじめ定義は出来ない。
その他、カプセル化まわりで色々と特徴があるけどそれはまた今度。


ループ処理その1

Python
for i in [0,1,2,3]:
    print i*2
AS3
for (var i:int = 0 ; i < 4; i++){
    trace(i*2);
}

とりあえず配列とセットで使う。


ループ処理その2

Python
list = ["a","b","c"]
for i in list:
    print i
AS3
var array:Array = ["a","b","c"];
for each(var p:* in array){
    trace(p);
}

AS3のfor eachとほぼ同様。ループ処理その1よりこっちの方が比較としては的確かも。


ループ処理その3

Python
list = [i*2 for i in range(0,10)]
AS3
var array:Array = [];
for (var i:int = 0 ; i<10;i++){
    array.push(i*2);
}

リスト内包処理。何かしらの処理結果を配列に格納するときにとても便利。ここら辺の機能がPythonって流石と思わせる。というか、こうしたループで文字列などのデータをゴニョゴニョ処理するのはPython、Perl、phpは基本的に得意なんだろうと思う。そしてAS3はつくづくその対局にいるのではないかと思ったりする。



最後に

ここに紹介した事以上にPythonは紹介すべき事が沢山あると思うけどとりあえず今のところは以上で。もし反響が良ければクラス周り、OOPとしての性質の違いに付いて比較したいと思います。

最後の最後に

ところでなぜPythonなのかというと、関西方面に引っ越ししたFlasherさんが、「Pythonいいよ!めちゃかわいいんですわ!yes!yes!!」と別れの間際に言ってた事と、AS3という言語を別の角度から見つめ直すにはPythonの様なシンプルなOOP言語が良いんじゃないかと思った事。
そして最終的にPythonをどこで使うかというと、http://onsight.la/のバックエンド。そんなわけでこれからはASerとPythonianのハイブリットを目指して頑張ります。あ、でもoFとかもやりたいなあ。

RSS + Contuct

  • rss
  • email

Credit

Copyright (C) 2007 kappa-lab.com.
All Rights Reserved.