4月 28
Windows環境とLinux(CentOS5.4)環境とで異なったのでメモ。
import locale
locale.setlocale(locale.LC_ALL,’ja’)
print locale.format(‘%d’, 123456789, True)
Windows環境ならこれでOKですが、Linux(CentOS5.4)環境なら、以下になります。
import locale
locale.setlocale(locale.LC_ALL,’ja_JP.UTF-8′)
print locale.format(‘%d’, 123456789, True)
環境の文字コードにも依存するんだと思います。環境のlocaleに関する情報は
locale.setlocale(locale.LC_ALL,”)
で取得できます。
Python2.5です。
4月 27
ハセテツは複数の言語を状況に応じて使い分けてきましたが、最近のWeb系開発はPython(+Django)がメインになってきています。
ちょっと前までRuby(+Rails)だったのですが、いろいろと考えるところもあり、乗り換えました。その乗り換えた理由をまとめてみようと思います。
まとめてみたら「やっぱりRailsじゃね?」となるかもしれません。w
Ruby(+Rails)
- Rails便利すぎる。
- コントローラとモデルが別々のファイルになってくれるのはソースが追いやすい。
- Railsを通さない画像やCSSはpublicフォルダに置けばよいのはわかりやすい。
- urlディスパッチャーがいまいち使いにくい。(知らないだけかも)
- APサーバはmongrel一択?
- VirtualHost使おうとするとApache+Passenger(mod_rails)だが、これが重い。(チューニングで速くなるのかも)
- というか、Railsがそもそも重い。
- ちゅーか、Rubyが重い、遅い。
- PassengerはWindowsじゃ動かない。
- mongrelもPassengerより激速軽快かというと、そうでもない。
- gem便利すぎ。
- ワンライナで書く人が多くて、Perlとおなじ匂いがする。
ハセテツが使っていたRubyは1.8で、速くなったといわれる1.9には触れていないのでもしかすると古いのかもしれません。でも、Railsって1.9には対応してないですよね?(本日現在)
Python(+Django)
- Django便利すぎる。
- 日本語の書籍、情報が少なすぎる。(ハマるとキツい)
- modelが一枚のファイルなので、大量のmodelがあると可読性が激しくダウン。
- viewファイルをフォルダで分けたくても、アプリケーションフォルダ直下以外にviewファイル置くなら「sys.path.append」しないといけない。(違う?)
- urlディスパッチャーのカスタマイズが超便利。
- mod_pythonが使えるので、Windows環境だろうがLinux環境だろうが気にせずVirtualHostが使える。
- 速い。
- 日本語大変。Shift_JIS怖い。
- easy_installでパッケージのインストールは楽だが、管理が悪夢。
メリットとデメリットが入り乱れました。見難くてすいません。
結局フルスタックのフレームワークということで、DjangoとRailsに関しては一長一短だと思います。個人的にはRailsの方が良くできてたかなぁと。
最終的に、「RubyonRailsは重い」というオチになってしまうのです。Rubyも、Railsも、です。ただ、これはRuby1.9が実は劇的に速くなっていて、1.9に対応したRailsがリリースされたらすべて解決されるのかもしれません。
それでも、いまのところPythonの軽快さ、シンプルさに満足しています。あと、GAEでPythonが動くのもいいですよね。
「Googleが導入した言語」というのがハセテツ的に琴線に触れたのかもしれません。
ミーハーですいません。w
4月 22
携帯メールでのブログエントリ投稿だったり、ユーザ登録だったり、メールのパイプ処理って結構重要だと思います。パイプさせなくてもcronで定期的にPOPすればいい話ですが、それだとユーザからのリクエストに対してシームレスに反応できないですよね。それはなんかイヤなんです。
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys, os, email
_mail = email.message_from_file(sys.stdin)
for item in _mail.walk():
if item.get_content_maintype()==’text’:
_file = open(‘/path/to/save/log.txt’, ‘a’)
_file.write(_mail['Subject']+’\r\n’)
_file.write(item.get_payload(decode=True)+’\r\n’) #body
_file.close()
elif item.get_content_maintype()==’image’:
_filename = item.get_filename()
_attache = open(‘/path/to/save/’+_filename, ‘wb’) #添付ファイルを保存
_attache.write(item.get_payload(decode=True))
_attache.close()
Python2.5です。
標準入力で読み込んで、要素(きちんと理解できてないのですが、boundaryで区切ったものってことだろうか)ごとにイテレートして、content_maintypeがtextなのかimageなのかで処理を分岐しています。ちなみに、content_maintypeはExcelファイルだったら「application」になります。
なお、エンコード処理入れてないのとエラー処理入れてないのです。いつものことなのです。
4月 21
隠蔽するっていうか、viewにごりごり書くのではなくてModelのメソッドで処理してしまおうという話です。このエントリの応用ですね。
import hashlib
class Member(models.Model):
name = models.CharField(max_length=32)
passwd = models.CharField(max_length=256)
def save(self, force_insert=False, force_update=False):
self.passwd = hashlib.md5(self.passwd).hexdigest()
super(Member, self).save(force_insert, force_insert)
Modelのsave()メソッドをオーバーライドしています。これで、登録フォームなどからPOSTされたデータをそのままsave()してもデータベース上には暗号化された状態で保存されます。
adminサイトで作成したユーザ情報なんかのパスワードとかも、暗号化して保存してくれます。便利便利。
4月 20
コンボボックスの<option>~</option>の値は動的に指定したいものです。が、Djangoでどうしたらよいものか、数時間悩みました。
これが意外と簡単で、こんなことで数時間悩んだ自分が情けなく、それでも発見した自分をほめてやりたく。w
class Form_hoge(forms.Form):
month = forms.ChoiceField()
_form = Form_hoge()
_form.fields['month'].choices = [(1,1), (2,2), (3,3)]
フォームを呼んだ後に指定するだけ。
なんですぐ気づかなかったんだろ。。。
Django1.1.1、Python2.5で動作検証。
4月 20
Djangoのモデルで集計クエリというと、1.0以降でcount()が使えますが、1.1になってさらに多機能になっていました。
from django.db.models import Sum
_result = Detail.objects.all().values(‘category’).annotate(price=Sum(‘price’))
for item in _result:
print item
Detailというモデルがあって、それをcategoryというフィールドでグループ化し、priceというフィールドのsum(合計)を求めています。
values(~)は必須ではありません。グループ化しないと全体のsumですね。
annotate(得られる結果の名前=Sum(集計対象フィールド))
です。サンプルの「price」をsum_priceにしても結果は得られます。
また、annotateで利用できるのはsumだけでなく、Avg、Max、Min、Countも使用できます。サンプルコードだとSumしかインポートしていませんが、「*」でまとめてインポートするか、「Avg, Max, Min, Sum, Count」をそれぞれインポートしてあげれば使用できます。
ちなみに、サンプルコードで得られるitemは、Detailモデルのインスタンスではありません。辞書です。最初ここに気づかず、「?」となっていました。w
4月 14
CSVのインポートとかをするときには良く使う手法でしょう。forms使えば入力された日付のバリデーション等はDjangoがやってくれるので、あんまり使用頻度は高くないかもしれません。
import time
import datetime
_date = ‘10/04/14′
_tpl = time.strptime(_date, ‘%y/%m/%d’)
print datetime.date(_tpl[0], _tpl[1], _tpl[2])
time.strptimeはタプルを返します。この例だと(2010, 4 , 14, 0, 0, 0, 2, 104, -1)が返ってきます。
第一引数が日付形式の文字列、第二引数が文字列のフォーマットです。「%y」は二桁の西暦です。
タプルを分解してdatetime.dateのインスタンスを生成すればできあがり。
4月 09
ネットで靴を買うのは少々抵抗がありましたが、時間という「減っていくだけ」のものとの比較をしたら、迷いは断ち切れました。
返品OKというのもポイントですね。
外で履いたらもう返品できないとか、水虫だったら返品できないとか、こまかい制限があるのかもしれませんが、それは追々調べてみよう。
4月 07
Pythonで文字列と文字列がどれくらい似ているか、を調べる方法です。これを活用すると、Google等の検索エンジンによくある「もしかして~」ができるようになります。名寄せ、表記ゆれの是正ですね。
import difflib
a = u”スパゲッティ”
b = u”スパゲティー”
print difflib.SequenceMatcher(None, a, b).ratio()
ハセテツの環境(WindowsXP、Python2.5.2)では、0.8333333~が返ってきます。0.6以上だと「よく似ている」そうです。これはレーベンシュタイン距離になるのかな?N-グラムではないよね。
コンテンツ内検索等を実装するとき、名寄せは重要になります。ECで商品検索したらタイプミスがあって欲しい商品にたどり着けなかった、なんてことは良くあります。これで必要な情報がユーザに届くようになるとうれしいですね。
4月 06
Djangoのフォームでclassを指定する方法です。Widgetクラスを使うのですが、情報が少ないような気がします。探し方ヘタ?
class Form_login(forms.Form):
mailadd = forms.EmailField(max_length=32,widget=forms.TextInput(attrs={‘class’:'form_entry’}))
passwd = forms.CharField(min_length=6, max_length=12,widget=forms.PasswordInput(render_value=False))
これで出力されるフォームには「class=”form_entry”」が追加されます。
パスワード側もWidgetクラスを使用していますが、Widgetクラスを活用するとDjangoのフォームってものすごく便利に活用できるような気がします。
Django 1.1.1、Python2.5で検証しました。