ラベル python の投稿を表示しています。 すべての投稿を表示
ラベル python の投稿を表示しています。 すべての投稿を表示

2009年2月17日火曜日

python code reading for WEB

Python力を高めるためのライブラリコードリーディング

私もDjangoからPythonに入った口ですが、
今もDjangoからPythonにはいる人が多いと思います。

まず読みたいのがこの記事。
Why so many Python web frameworks?

いかにフレームワークを作るのが簡単かがわかり、自分で作ってみたくなる。
「ここで、Djangoなんかたいしたことないじゃん。
もっといいのを私は作れるよ!」
といって色々便利なフレームワークを組み合わせてみると、
ほかのフレームワークのよいところがはじめて見えてくる。

こうして色々試すとようやく「仕事」で使う上でのDjangoの魅力をようやく理解できる。
もちろん、Djangoには欠点がある。
contrib.authの融通の利かなさとか、
modelsがややお間抜けとか、
Routingのエラーメッセージとか、
templatetagの仕様だとか、
動的なFormとか。
解決したライブラリををそれぞれ作ってみたけど、個人使用ならともかく公開はできない。
ただ、解決方法をIRCでねちっこくつぶやくだけ。
だって、メンテしたくないから。
もっといい方法を思いついたら飛び移りたいじゃん。


っと、脱線してしまったけど、
とりあえず、最初にDjangoを読むよりは、個別のライブラリを読むほうが入門しやすい。
フレームワーク以前のPythonの言語自体については、
Code Like a Pythonista: Idiomatic Pythonを読んでください。

みんな、Pythonを愛してください。

2009年1月27日火曜日

web2py

これほどまでに万能(変態)の名がふさわしいフレームワークがあるだろうか。

・フルスタック
・1からアプリケーションを開発できるエディタつき万能WEBADMIN
・GUIでER図を描くSQL Designer
・Stan-likeなHTML BuilderとDjangoとPSPのいいとこどりテンプレート
・とりあえずBEAUTIFY
・Railsのflash
・Model連動Form
・SQLAlchemyに対抗心メラメラなORM
・gae-likeモデル連動自動スキーマ変換
・GQL生成するので、GAEでもModel変更不要。
・ついでにCASも提供しておきます。
・Exceptionから自動Ticket発行
・Rails-likeのURL-RoutingにReverseがつき、Regex機能も併せ持つ完ぺき主義。
・request,responseなど、実用性だけを考えた大量のglobalオブジェクト
・ValidatorまでGlobalはマジでやめてくれ、IS_EXPR … 恐ろしい子

必要な機能はすべてそろっている。
後は勇気だけ。

変態だから人に勧めにくい。
GAEで使うフレームワークを探していたときに見つけた。
この豊富な機能は感動。

個人でいくつかGAEように作ったけど、会社では使いたくない。


------
ようやく書いた。
書こうと思ってメモ書きだけして、放置してあるのが多数。
ブログの使い方を間違えているな。

もういいやと思ってメモを消してしまったことも多いし、
メモでもいいからとりあえず公開して、その後追加、あるいはまとめを書くスタイルに変えなければ。


書きかけで放置してあるメモはあと5つ。
・django command拡張
・django-things
・Seasar2
・ipython
・本文抽出

2009年1月9日金曜日

download mass images 1

突然壁紙がたくさんほしくなったので、
壁紙がいっぱい集まっているところからちょいといただきます。

少し眺めていれば、以下のURLのように連番が発見できます。
http://www.backgroundsarchive.com/backgrounds/9124

まあ、ざっと見て20000以下なので、そこからbashを使います。
まずは10ほどで試してみましょう。
% echo http://www.backgroundsarchive.com/backgrounds/{1..10}
なんかたくさん表示されましたね。
OK、続けて
% echo http://www.backgroundsarchive.com/backgrounds/{1..10}|xargs -n1 echo
Bravo! これで分かりましたね。

あとはBeautifulSoupでいただいてしまいましょう。

import sys, re, urllib
from urlparse import urlparse, urljoin
from BeautifulSoup import BeautifulSoup

def download(url):
print 'down '+url
urllib.urlretrieve(url, url[url.rfind('/')+1:])

def parse(url):
print 'parse '+url
soup = BeautifulSoup(urllib.urlopen(url).read())
a = soup('a', href=re.compile(r'^/images/pub/\d+/\w+\.jpg$'))
map(lambda a:download(urljoin(url, a.get('href'))), a)

if __name__ == '__main__':
parse(sys.argv[1])

wally.pyとでも命名して即実行。
% time echo http://www.backgroundsarchive.com/backgrounds/{1..10}|xargs -n1 python wally.py
echo http://www.backgroundsarchive.com/backgrounds/{1..10} 0.00s user 0.00s system 42% cpu 0.001 total
xargs -n1 python wally.py 1.52s user 0.84s system 3% cpu 1:16.55 total
うーむ、信じられないほど遅い。
ブラウザだと少し早いからUAによる制限でしょうか。
まあ、しょうがない。

同時にダウンロードしちゃえば早いじゃんというのは自然な発想です。
コネクションが多すぎるとダメって聞いたことがあるので6つぐらいにしましょう。
% time echo http://www.backgroundsarchive.com/backgrounds/{1..10}|xargs -n1 -P6 python wally.py
echo http://www.backgroundsarchive.com/backgrounds/{1..10} 0.00s user 0.00s system 40% cpu 0.001 total
xargs -n1 -P6 python wally.py 1.48s user 1.45s system 11% cpu 26.645 total
これで六本同時に走ります。
うん、多少早くなりましたね。

念のため、User-Agentをかえてみます。
こんなのをimport urllibの下に書いておけばいいでしょう。

class FFURLopener(urllib.FancyURLopener):
version = 'Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9.0.5) Gecko/2008120122 Firefox/3.0.5'
urllib._urlopener = FFURLopener()

そして実行
% time echo http://www.backgroundsarchive.com/backgrounds/{1..10}|xargs -n1 -P6 python wally.py
echo http://www.backgroundsarchive.com/backgrounds/{1..10} 0.00s user 0.00s system 45% cpu 0.001 total
xargs -n1 -P6 python wally.py 1.52s user 1.32s system 82% cpu 3.428 total
げええ。
というわけで最適化に教科書なし。
遅いところに適切に対応しましょう。

さて、単純な連番ならこれでいいのですが、今回は全件取るつもりはありません。
序盤を集めたところマーブルばっかりで、動物とか風景がもっとほしい。
トップ画面からクロールしてほしい画像の一覧を作ったほうが好みの画像が集まりそうです。
トップページを見ると21ジャンルほどありますね。
巡回して21ジャンルから100枚ずつぐらいのリストを作るプログラムを書いて、
% python wally.py http://www.backgroundsarchive.com/desktop/|xargs -n1 -P6 wget
でうまくいきそうです。

予想外に長くなってしまってので次回へ続く。

2009年1月8日木曜日

Ajax file upload

byteflowのデコレータから引用していたけど、FileUploadに対応させました。

Ajaxでは
request.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest'
が成り立つのですが、FileUploadはiframeを使いますのでつきません。
iframeでsubmitした場合、application/jsonにすると、ダウンロードが始まってしまうため、逃げます。

def ajax_request(func):
def wrapper(request, *args, **kw):
if request.method == 'POST':
response = func(request, *args, **kw)
else:
response = {'error': {'type': 403,
'message':'Accepts only POST request'}}
if isinstance(response, dict):
if request.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest':
class JsonResponse(HttpResponse):
def __init__(self, data):
super(JsonResponse, self).__init__(
content=simplejson.dumps(data),
mimetype='application/json')
return JsonResponse(response)
else:
# for file upload
class IframeResponse(HttpResponse):
def __init__(self, data):
super(IframeResponse, self).__init__(
content=''%simplejson.dumps(data))
return IframeResponse(response)
else:
return response
return wraps(func)(wrapper)


jquery.form.jsを使うと、具合が大変よろしいです。

$('#image_form').ajaxForm({
dataType: 'json',
beforeSubmit: function() {if (!$('#icon').val()) return false},
success: function(data) { render(data) },
resetForm: true
})

dataTypeは'json'で。
beforeSubmitの第1引数のformDataはnameで引けないので不便。
第2引数のjqFormで、jqForm[0].icon.valueでもOK。
もっといい指定方法は知りたい。
clearFormがなぜか効かなかったのでresetForm。

jquery.blockUI.jsで画像選択やアップロード画面を出すときれい。

jquery.js必須

2008年12月7日日曜日

Guido's new method definition idea

http://groups.google.com/group/comp.lang.python/browse_thread/thread/5457b8649040f7ea

最近のホットな話題

class C:
def self.method( arg ):
self.value = arg
return self.value

というシンタックスシュガーを3.1で入れようかっていう話題。


self.method = lambda arg: foo(arg)

に似てていいじゃんってな意見もある。
ただ、そこから、Rubyチックにしろとかみんながすき放題言いまくって大盛況。
とりあえず、現時点ではまとめ人おつ。

2008年12月4日木曜日

Pythonの配列操作

http://d.hatena.ne.jp/tachikawa844/20081204/1228381610

joinについては
",".join(str(s) for s in score)
か
",".join(map(lambda s:str(s), score))
が主流なはず

あと、
spliceについて
removed = array[1:5]
array[1:5] = xyz
とすれば実現できるはずだけど、1:5の指定を一度にしたいなー。
よく考えたら配列の切り出しと改変を両方行っているわけか。
こんな風に使ったことがないけど、どういうときに便利なんだろうか。
spliceって変な関数だな。
あ、popと一緒か。
でも代入だしなー。

2008年11月21日金曜日

python urllib.urlretrieve で進捗表示しつつダウンロードのメモ


import sys
import urllib

def _reporthook(blocknum, bs, size):
sys.stdout.write("%4d%%\r"%(blocknum*bs*100/size))
sys.stdout.flush()

if __name__ == "__main__":
uri = sys.argv[1]
dest = uri[uri.rfind('/')+1:]
urllib.urlretrieve(uri, dest, _reporthook)
print

参考: http://subtech.g.hatena.ne.jp/cho45/20081120/1227178806
http://blog.livedoor.jp/dankogai/archives/51141631.html
printfやputsはflushいらんの?
pythonはprintでもダメだった
よくわからない

2008年6月11日水曜日

netmask

IPアドレスの制限で、ネットマスクの対応が見つからなかった。
128.255.63.0/24なら
アドレスを16進数に直して80ff3f00と2**24-1<<(32-24) & targetを比較すればいいのかな?

式はいくつか思いつくけど、正攻法はどんなものだろうか。
  • 2**32-(1<<32-m)
  • 2**m-1<<32-m

def ip_valid(addr):
for s in IP_RANGE:
t = s.split('/')
if len(t) == 1:
ip = t[0]
mask = '32'
else:
ip = t[0]
mask = t[1]
mask = int(mask)
n = ip2num(ip)
if ip2num(addr) & 2**32-(1<<32-mask) == n:
return True
return False

def ip2num(ip):
n = 0
for i in ip.split('.'):
n <<= 8
n += int(i)
return n

IP_RANGE = [
'210.153.84.0/24',
'123.108.237.9',
'202.179.204.0/24',
'61.202.3.0/24',
]