Entries tagged “Python”

SQLAlchemyメモ

written by shn, on Aug 5, 2009 1:49:00 PM.

毎回ググるので、メモっておく。 このブログがSEOされて、このエントリが上位に来れば、次ググる時楽になる寸法だ!

INSERT IGNORE INTO ...

insert(..., prefixes=['IGNORE'])

SELECT ... FOR UPDATE

select(..., for_update=True)

随時更新したい。

WebShot 2009

written by shn, on May 21, 2009 10:09:00 PM.

昨日の夜中に突然ウェブページのSnapShotを撮るサーバが欲しくなった。SBMのサイトによくある奴。FreeBSD / Linuxでやりたいのよね。

先人の知恵を探すのだが、良い検索語がわからない。「Webnailと呼ばれているらしい」ということでGoogleさんに聞いてみたら「もしかして: Webmail」とか言われて死にたくなった。結局 "Webpage screenshot"とかで良かったよ。

んで探すと良く出てくるのがXvfb + firefoxの組み合わせ。2006年のSimpleAPIの時にみなこぞって作ってたらしく、その頃の話が出てくる。 この方法は、Firefoxを使っているので、いろいろな通知系を殺さないといけないのと、そもそもonLoadのイベントが取れないからsleepを適当にやってからScreenshot撮るってのがぜんぜんだめ。

んでもうちょっと探すと、Xvfb + QtWebKitを使った話がでてきた。これだとonLoadのイベントが取れる。

試してみたら、かなり簡単に撮れて拍子抜け。PortsでXorg + Qt一式のビルドに3、4時間かかったけどな!

元コードをちょっと弄って、scrollbarを消してみた

frame = self.page.mainFrame()
# hide menu bar
frame.setScrollBarPolicy(Qt.Horizontal, Qt.ScrollBarAlwaysOff)
frame.setScrollBarPolicy(Qt.Vertical, Qt.ScrollBarAlwaysOff)

縦長のScreenShotを撮るには baseSize = QSize(800, 600) # まず基準となるサイズにする self.page.setViewportSize(baseSize) # contentSizeの方が多きかったら(スクロールバーが出てたら) contentSize = self.page.mainFrame().contentsSize() if contentSize.width() > baseSize.width(): self.page.setViewportSize(contentSize)

あと僕の環境だと、Qtの画像縮小は汚ないのでPILとかを使ったほうが良い。

これの前段にSquidとか挟むべきなんだろうな。まぁなにはともあれ、やりたい事はできた

自己参照のrelation @ sqlalchemy 0.5

written by shn, on Apr 13, 2009 12:31:00 PM.

自己参照型のrelationを作ろうとしていて、子供を追加しても「循環参照だ!」って怒られてプチ困った。 マニュアル読んだら答かいてあったよメモ

以下、Adjacency List Relationships - Mapper Configuration からコピペ

親 > 子は普通で良い

mapper(Node, nodes, properties={
    'children': relation(Node)
})

子 > 親はremote_sideという引数にカラムを指定する

mapper(Node, nodes, properties={
    'children': relation(Node, backref=backref('parent', remote_side=[nodes.c.id]))
})

remote_side

used for self-referential relationships, indicates the column or list of columns that form the "remote side" of the relationship.

とのこと。これ以上はコードを追ってないので、なんでこうしないと普通の1:Nとして関係が作れないかはわからず…

Werkzeugで遊ぼう! - Routing編

written by shn, on Mar 7, 2009 2:34:00 AM.

リクエストから、各URLへと対応するハンドラを導くのに、Werkzeugではwerkzeug.routingを使う。

wz_routing.py

#! -*- coding:utf-8 -*-
from werkzeug import run_simple
from werkzeug.routing import Map, Rule, Submount, Subdomain

class WSGIApplication(object):
    def __init__(self):
        self.url_map = Map([
            Rule('/hello', endpoint='hello'),
            Rule('/hello/<string:lang>', endpoint='hello'),
        ])
        self.url_adapter = self.url_map.bind('localhost')

    def __call__(self, environ, start_response):
        endpoint, arguments = self.url_adapter.match(environ['PATH_INFO'])

        handler = getattr(self, 'handle_%s' % endpoint)
        return handler(environ, start_response, **arguments)

    def handle_hello(self, environ, start_response, lang='en'):
        writer = start_response('200 OK', [('Content-Type', 'text/plain; charset=utf-8')])
        if lang == 'en':
            return ['Hello']
        elif lang == 'ja':
            return ['こんにちわ']
        elif lang == 'he':
            return ['הלו']
        return ['no hello yet']

if __name__ == '__main__':
    run_simple('localhost', 4000, WSGIApplication())

$ python wz_routing.pyして、$ curl http://localhost:4000/hello とか、 $ curl http://localhost:4000/hello/ja とかしてみるといろいろなhelloが楽しめると思う。

Ruleには、<int>やら、<float>やらも使えるので、/blog/archive/2009/03/とか、twitter.com/shn/repliseみたいなナウいURLが設計しやすくて良いですね~

__call__の中身は、以下のようにも書き換えられる。

return self.url_adapter.dispatch(
    lambda e, a: getattr(self, 'handle_%s' % e)(environ, start_response, **a),
    path_info=environ['PATH_INFO']
)

goodbyeも楽しみたいなーと思って、/goodbyeにアクセスするとNotFound例外が飛ぶ。こいつもwsgi的な奴なので、ちょちょっとするとエラーを表示してくれる。

from werkzeug.exceptions import HTTPException
try:
    endpoint, arguments = self.url_adapter.match(environ['PATH_INFO'])
except HTTPException, e:
    return e(environ, start_response)
else:
    ...

Submountを使うと、Ruleの塊を指定したディレクトリ以下にマッチしてくれるようにしてくれる。似たようなのにSubdomainてのもあるけど、まだ使ったこと無い。subdomain毎にbind()しないといけないのかな?

Werkzeugで遊ぼう! - とりあえず編

written by shn, on Feb 27, 2009 8:49:00 PM.

ザインに入信したので次はWerkzeugだ!

Werkzeugは小気味の良いWSGIのユーティリティ集で、やはりpocooタンが開発している。pocooタンかわいいよpocooタン
C#よりC++, MFCよりWTL, apacheよりnginxな男はDjangoよりWerkzeugを選ぶのである。

前置きはおいといて、まず開発支援系の機能から試していくことに。

run_simple

werkzeugのHTTPサーバを使った最小コードはこんな感じかしら。手元でテストする分には十分げ

wz_first.py

#! -*- coding:utf-8 -*-
from werkzeug import run_simple

class WSGIApplication(object):
    def __call__(self, environ, start_response):
        writer = start_response('200 OK', [('Content-Type', 'text/plain; charset=utf-8')])
        return ['Hello', 'הלו', 'こんにちわ']

def main():
    run_simple('localhost', 8080, WSGIApplication(), use_reloader=True)

if __name__ == '__main__':
    main()

use_reloader=Trueにすると、forkして、コードに変更がありしだい子プロセスを立ち上げなおす。

スクリプト

wekrzeug.scriptを使うと、コマンドラインからいろいろ出来る!

def main()
    from werkzeug import script

    action_runserver = script.make_runserver(WSGIApplication, use_reloader=True)
    action_shell = script.make_shell(lambda: {'app': WSGIApplication})
    script.run()

コマンドラインから、script.run()を呼び出したフレームのaction_xxxを呼び出せる。
例えば、$ python wz_first.py runserverすると、action_runserverさんが呼び出される。

ワースゴイヤ!

Pythonの最小セット

written by shn, on Feb 24, 2009 6:28:00 PM.

Python(2.6@win32)を起動するだけなら、以下のlibがあれば良いようだ

site
    os
        ntpath (win32)
            stat
            genericpath
            warning
                linecache
                types
        UserDict(win32)
            _abcoll
                abc
        copy_reg

    encodings
        codecs

site.pyはいじって、site-packages等を読み込まないようにしている。

sys.setdefaultencoding('utf-8')とかしないなら、encodings以下もいらないのかな。codings:utf-8なんてスクリプトが読めなくなるかな。

_zipimportは組込みなので、上記パッケージはzipできる。zipすると57KBととてもスッキリ

Boost.Python@MSVCでpython-debuggingが

written by shn, on Feb 23, 2009 6:20:00 PM.

多分これと一緒。 Boost.Pythonをpython-debuggingにしてビルドしたものを使うと、Pythonの関数を呼んだ時に逝くという問題。 環境は恐らくWindowsのみで、うちの場合はboost 1.38.0, MSVC 9, Python 2.6。

原因はpython-debugging=onにしてできる、boost_python-vc90-mt-gy-1_38.dllPython26.dllと、Python26_d.dllの両方にリンクしてるからっぽい。

深く追うのがめんどくさかったので、tools\build\v2\tools\python.jam L:102に、condition = <python-debugging>on ;を挿入して無理矢理解決。

ざっと見た感じ、tools\build\v2\build\toolset.jam L:32initを空で呼んでいるせいで、 python.jamのinitに$(condition)が渡されてないのかなぁ、と。

bjamの引数に-d 7とか渡すとbjam内の引数と関数呼び出しを全部出力できて便利。 (ref: bjam usage)