2010年4月29日木曜日

OSXのApache2でDjangoをデプロイするには



Snow Leopard付属のApacheでDjangoを動かしてみたのでまとめておこうと思います。


CGIだとやたら遅いのでFastCGIを使うことにします。


Apache で FastCGI を扱うモジュールのうち、今回は mod_fcgid を試してみました。


mod_fcgid をインストール


http://httpd.apache.org/mod_fcgid/ に svn レポジトリのURLがあるのでそこからダウンロードします。



% svn checkout http://svn.apache.org/repos/asf/httpd/mod_fcgid/trunk mod_fcgid
% cd mod_fcgid
% ./configure.apxs
% make
% sudo make install


flup をインストール



% wget http://www.saddi.com/software/flup/dist/flup-1.0.2.tar.gz
% tar zxvf flup-1.0.2.tar.gz
% cd flup-1.0.2
% python setup.py build
% sudo python setup.py install


Apache で mod_fcgid を使えるように設定


/etc/apache2/httpd.conf に


LoadModule fcgid_module libexec/apache2/mod_fcgid.so


を記述


Django のプロジェクトを移動


今回は /Library/WebServer 以下に置きました。


ディレクトリ名は django です。


fcgid.conf を設定


fcgid_module 用の設定を記述。場所は /etc/apache2/other/fcgid.conf です。



<IfModule fcgid_module>
AddHandler fcgid-script .fcgi
SocketPath /tmp/fcgidsock
SharememPath /tmp/fcgidshm
IPCCommTimeout 40
IPCConnectTimeout 10
</IfModule>


django.conf を設定


django 用の設定を記述。場所は同じく /etc/apache2/other/django.conf



Alias /django/ "/Library/WebServer/django/"
Alias /django "/Library/WebServer/django/"
<Directory /Library/WebServer/django/>
Options +ExecCGI +FollowSymLinks
AllowOverride all
Order allow,deny
Allow from all
</Directory>


.htaccess を設定


/Library/WebServer/django 内に .htaccess を用意します。



AddHandler fcgid-script .fcgi
RewriteEngine On
RewriteBase /django/
RewriteRule ^(media/.*)$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(dispatch\.fcgi/.*)$ - [L]
RewriteRule ^(.*)$ dispatch.fcgi [QSA,L]


dispatch.fcgi を用意


自分の場合は MacPorts でインストールした python を使うように設定してますが、


その辺りは適宜読み替えてください。



#!/opt/local/bin/python
import sys
import os
sys.path.insert(0, '/Library/WebServer')
os.environ['DJANGO_SETTINGS_MODULE'] = 'django.settings'
os.environ['PYTHON_EGG_CACHE'] = '/tmp'
os.environ['PYTHON_PATH'] = '/opt/local/lib/python2.6/site-packages'
from django.core.servers.fastcgi import runfastcgi
runfastcgi(method='threaded', daemonize='false')


以上の設定が終わった後にWebサーバを再起動して、


http://localhost/django/ で動いてるのを確認しました。


ちなみに、fcgid 入れた当初はアクセスするとなぜか apache が落ちるという症状が出てました。


調べてみて http://ktjx.blogspot.com/2008/02/mac-os-x-php5-apache2-modfcgid.html を参考に解決。





で、ここまで設定した後で settings.py で DEBUG = False にするのを忘れていました。


伴って必要な設定をもう一つ済ませておきます。


静的なファイル(テンプレート、CSS、画像など)の設定


Django はこれらのファイルを提供しないらしいです。 http://djangoproject.jp/doc/ja/1.0/howto/static-files.html


ただし、DEBUG = True の場合は例外です。よって、DEBUG = False にする場合はなにかしら設定をする


必要があります。


今回は、django/templates に静的なファイルをまとめてしまうことにしました。


で、/Library/WebServer/other/django.conf に一行書き加えます。


django 用の設定を記述



Alias /django/ "/Library/WebServer/django/"
Alias /django "/Library/WebServer/django/"
Alias /django/media "/Library/WebServer/django/templates" # <- 追加
<Directory /Library/WebServer/django/>
Options +ExecCGI +FollowSymLinks
AllowOverride all
Order allow,deny
Allow from all
</Directory>


これで DEBUG = True にしても問題なく動作しました。





2010年4月26日月曜日

launchctl を登録



launchctl を使って mediatomb を登録しようといろいろ試してたけど、上手くいかないので mediatomb を実行するシェルスクリプトを書いてそれを登録するようにした


startmb.sh



#!/bin/sh
ip=192.168.0.1
add=/Users/user/Movies
config=/Users/user/.mediatomb/config.xml
port=49152
/usr/bin/mediatomb --ip $ip --add $add --config $config --port $port --daemon


startmb.sh をパスが通ってるディレクトリ(今回は $HOME/bin)に置いておいて、launchctl に読み込ませるための startmb.plist を作成。



<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">;
<plist version="1.0">
<dict>
<key>Label</key>
<string>startmb</string>
<key>ProgramArguments</key>
<array>
<string>/Users/user/bin/startmb.sh</string>
</array>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>



これを ~/Library/LaunchAgents/startmb.plist に置く。


で、launchctl を実行



$ launchctl load -w ~/Library/LaunchAgents/startmb.plist
$ launchctl start startmb


これで mediatomb が動いた。


同様にして自作のWebアプリも登録しといた。





2010年4月22日木曜日

Python2.7のCounterを使ってみた



python2.7(2010年4月21日現在まだベータですが)で追加されるクラスの一つに Counter があります。


7.3. collections ? Container datatypes — Python v3.2rc2 documentation


その名の通り何かしらのデータをカウントするときに使えるクラスです。


例えば今までは



d = {}

d['foo'] = d.get('foo',0) + 1
d['bar'] = d.get('bar',0) + 1
d['foo'] = d.get('foo',0) + 1

for key,value in d.items():
print key,value


なんて書いていたのが



from collections import Counter

c = Counter()

c['foo'] += 1
c['bar'] += 1
c['foo'] += 1

for key,value in c.items():
print key,value


で済むようになります。


また、most_common()を使えば手軽にソートできます(上記リンクから参照)。



>>> # Find the ten most common words in Hamlet
>>> import re
>>> words = re.findall('\w+', open('hamlet.txt').read().lower())
>>> Counter(words).most_common(10)
[('the', 1143), ('and', 966), ('to', 762), ('of', 669), ('i', 631),
('you', 554), ('a', 546), ('my', 514), ('hamlet', 471), ('in', 451)]


今までのように辞書使ってると、一旦リストに変換して……とか面倒なステップを踏んでたのでこれはありがたいですね。


ちなみに、github に試しに作ったソースを載せました。


gist: 373850 - python2.7で追加されたCounterを試しに使ってみた。従来の辞書との使い方の比較。- GitHub