EmacsのPython開発環境を整えた

macbookを買ってからずっとcarbon emacsを使っていたんだけど、思うところあって23系に変更した。

ここを参考にしながらソースコードを落としてきてインストールした。

python開発環境はemacs-for-pythonがよさそうだったんだけど自分の環境ではpyflakesが動かなかったので、深入りする前にやめた。今度また時間があるときにチャレンジする。

結局以下のサイトを参考にしてflymake, pyflakes, pep8, virtualenv, noseが動くようにしておいた。

emacs

出来上がったelisp

(add-hook 'python-mode-hook
                   '(lambda()
                        (setq indent-tabs-mode nil)
                        (setq indent-level 4)
                        (setq python-indent 4)
                        (setq tab-width 4)))

;; flymake+pyflakes+pep8
; http://d.hatena.ne.jp/cou929_la/20110525/1306321857

(add-hook 'find-file-hook 'flymake-find-file-hook)
(when (load "flymake" t)
  (defun flymake-pyflakes-init ()
    (let* ((temp-file (flymake-init-create-temp-buffer-copy
                       'flymake-create-temp-inplace))
           (local-file (file-relative-name
                        temp-file
                        (file-name-directory buffer-file-name))))
      (list (expand-file-name "~/bin/pycheckers")  (list local-file))))
  (add-to-list 'flymake-allowed-file-name-masks
               '("\\.py\\'" flymake-pyflakes-init)))

(load-library "flymake-cursor")

;; virtualenv
; https://github.com/aculich/virtualenv.el
(require 'virtualenv)

;; nose.el
; https://bitbucket.org/durin42/nosemacs/src/9302529e68be/nose.el
(require 'nose)
(add-hook 'python-mode-hook
          (lambda ()
            (local-set-key "\C-ca" 'nosetests-all)
            (local-set-key "\C-cm" 'nosetests-module)
            (local-set-key "\C-c." 'nosetests-one)
            (local-set-key "\C-cpa" 'nosetests-pdb-all)
            (local-set-key "\C-cpm" 'nosetests-pdb-module)
            (local-set-key "\C-cp." 'nosetests-pdb-one)))

M-x virtualenv-workonでvirtualenvが使えるうえにemacsからnosetestsをはしらせることが出来るので快適だ。

ProductName エキスパートPythonプログラミング
Tarek Ziade
アスキー・メディアワークス / 3780円 ( 2010-05-28 )


ソースコードリーディングにはpycco

doccoのpython版((doccoはテーブルタグ使っているけどpyccoはdivなので出力するhtmlはちょっと違う))だけどオプションが幾つかあって、pオプションがソースのディレクトリ階層を保持したままドキュメントを生成するのでちょっと便利。

pの使い方は、例えばSphinxのtar-ballをダウンロード、展開して

cd sphinx
find . -name "*.py" -print0| xargs -0 pycco -p

ってやるとdocsディレクトリに階層を保持された形で全てのコードのドキュメントが作成されるので、ソース自体にコメントを入れながら動きを把握するのに便利。今までsphinxでメモってたけどこっちのほうが断然理解しやすい。

rオプションとかつけて再帰的にたどってくれればwatchオプションと併用出来ていいかもと思うんだけど。

restもサポートされる感じなのでそれもちょっとよさげ。

ただ、まだちょっとバグってるので快適とは言いがたいが、楽しみだ。

Backbone.jsみたいな注釈付きのソースコードをつくるやつ(docco)

Backbone.jsのannotated source読みやすいわと。

いつものようにsofを探した。

doccoを使えばいいらしい。ちなみにpythonだとPyccoがあるのでどちらかを使えばいいかな(両方入れたが)。

今、spinehemのソースコードを読んでいるので、明日のつくる会ではdoccoを使った黙々注釈付けをやろうかな、というかやる。

というわけで、明日は静岡デベロッパーズつくる会#5です。一人だと作業に集中できないわーとか、つけナポリタン気になるわーというヒトは気軽にフラッと寄ればいいと思います。

ちなみにお菓子の持ち込み可です。菓子をつまみながらコーディングしましょう。

Pythonプロフェッショナルプログラミングを読んだ

昨日、近所の本屋に行ったら追いてあったので、衝動買いしてそのまま読み始めて、今日仕事から帰ってきて少しよんだら読み終わったので、400ページ超えの厚さの割にはさくさく読める。

ProductName Pythonプロフェッショナルプログラミング
ビープラウド
秀和システム / 2940円 ( 2012-03-26 )


広く浅めのエキスパートPythonプログラミングかなぁと思っていたけど、カバーしている範囲が結構違っていて、本書はチーム開発のやり方with Pythonっていう感じかな

virtualenvを使った仮想環境の構築とMercurialでのバージョン管理といった基本からはじまって、 ITS(Trac)のインストールと運用のコツ、Sphinxを使ったドキュメント基盤の整備とかJenkinsを利用した継続的インテグレーションの話がPart1,2のチーム開発のサイクルで書かれている。書籍としてまとまっていると手っ取り早く把握できていいですね。僕はココらへんをブログを漁ったりして仕入れたので若干苦労した。

さて、僕が興味を持ったのがPart3のサービス公開のところで、Fabricの使い方とかgunicorn,nginxの使い方、GAE周りの情報だったので非常に参考になった。

ちなみにuWSGIも気になってるんだけどその話題はなかったと思う。いまだとどっちを使うのがいいんだろうか。 apache+mod_wsgiで動かしているこのブログもnginxに移行したい。

あとpip freeze便利。これでインストールしたモジュールをテキストファイルにリスト化しておいて、

$ pip install -r list.txt

ってやれば必要なモジュールを入れられるのでvirtualenvと相性がいいですね。

というわけで最近のFlask開発で入れてるモジュールをリスト化してみた。

Flask==0.8
Flask-DebugToolbar==0.6.2
Flask-SQLAlchemy==0.15
Flask-Script==0.3.3
Jinja2==2.6
SQLAlchemy==0.7.6
Werkzeug==0.8.3
argparse==1.2.1
blinker==1.2
pyjade==1.0.1
wsgiref==0.1.2

pyjadeはいいですね。

pyjadeを1.X系にあげた

いままで0.6.1を使っていたのだけど、バージョンが上がってJade互換になったそうなので週末を使って自分のブログシステムに対応させていた。

テンプレート周りの設定が色々変わっていてエラー吐きまくったんだけど、出来上がったテンプレートはJinjaっぽさ({{ }})が排除されていい感じに洗練されてきている。

JadeがヨサゲなのはBrunchと一緒に開発すればサーバーサイド(Flask)とクライアントサイド(backbone.js)で同じテンプレート言語を使えるっていうのもありそう。そういうwebアプリを作ってみたいと思っているが。

それから、1.0はutf-8のテキストを渡すとエラーになるバグがあったのでgithubのissueに登録したらすぐに対応してもらえて1.01になったので、サーバーのpyjadeのバージョンを上げて動作を確認してデプロイして、酒を飲みながらこのエントリを書いている。ソーシャルコーディングってサイコーですね。製薬系みたいな閉鎖系では味わえないスピード感がある。

0.6.1から1.0での変更点

url_forの使い方

ダブルクォーテーションとか中括弧が省略できるようになっている

autoescape

0.6.1だと

autoescape(false)= entry.content

ってやればJinjaのautoescapeが使えたんだけど1.0ではautoescapeタグになってしまう。

.contents= entry.content|safe

ってやってフィルタをかますようにした。

pygamess 0.3.0

バグフィックスしたり基底関数まわりを追加してバージョンをちょっとあげた。

一番大きな変更はデフォルトでrungmsを使わないようにしたことで 直接ddikickを叩くことにしたことか。それでgamessのパスをどうしようかなぁと。

とりあえずコンストラクタで直接指定してない場合は

  1. 環境変数GAMESS_PATHを調べる
  2. PATHの中からddikick.xのあるディレクトリを探して、それを選択する

それとは別にrungmsのpathを探したりもしている(僕の場合はrungmsを/usr/local/binに置いている)のでちょっとくどいやり方になってしまった。

それから、コンストラクタにオプションを渡せるようにしたんだけど、これだと、gamessのインプットいじるのと変わらないので、もう少しスマートな指定方法も用意したほうがいいかなぁと思った。

水分子を基底関数を変えながらエネルギーを計算する例。このくらいだったら対話環境でサクッとうごく。

>>> import pybel
>>> from pygamess import Gamess
>>> g = Gamess()
>>> mol = pybel.readstring('smi', 'O')
>>> mol.make3D()
>>> g.run(mol).energy
-74.96450135
>>> g.run_type('optimize')
>>> g.run(mol).energy
-74.9659012146
>>> g.basis_set('3-21G')
>>> g.run(mol).energy
-75.585959758
>>> g.basis_set('6-31G')
>>> g.run(mol).energy
-75.9853591564
>>> g.basis_set('6-311G')
>>> g.run(mol).energy
-76.0109546389
>>> g.basis_set('6-31G*')
>>> g.run(mol).energy
-76.0107465155
>>> g.basis_set('6-31G**')
>>> g.run(mol).energy
-76.0236150193

最近ちょっと困っているのが、構造最適化で収束しないのをどうやって収束させるかという。6-31G*くらいでmopacみたいなノリで計算できるようにしたい。

素晴らしいスピン多重度

openbabelのコンバーターがバグってる。

>>> import pybel
>>> from pygamess import Gamess
>>> g = Gamess()
>>> mol = pybel.readstring('smi','C')
>>> mol.make3D()
>>> nmol = g.run(mol)
>>> nmol.OBMol.GetTotalSpinMultiplicity()
1882919584

pybelでanilineをnitrenium ionに変換する

なぜnitrenium ionにする必要があるのかはここではふれないので、ココらへんを見てください。

import pybel
smarts = pybel.Smarts("c[#7]([#1])[#1]")

mol = pybel.readstring('smi', 'c1ccccc1N')
mol.make3D()
matches = smarts.findall(mol)
mol.OBMol.DeleteAtom(mol.atoms[matches[0][2]-1].OBAtom)
mol.OBMol.SetTotalCharge(1)
print mol.write('mol')

分子に修飾をしたい時はpybelにメソッドがないので、OpenBabelのオブジェクトを直接触る必要があるのであまりスマートではない気がする。

Python modules for Humans

for Humansなモジュールが気になったのでPyPiを探してみた

paperはちょっと気になるが、開発中。

pythonコードをデーモン化するモジュール

みつけたのでソースコードを読んでみたら、かなり参考になった。

51行目

resourceモジュールを使っているのを見るのははじめてだ。

for fd in range(resource.getrlimit(resource.RLIMIT_NOFILE)[0]):
    try:
        os.close(fd)
    except OSError:
        pass

57行目

dupすると未使用の中で最小のディスクリプタに割り当てられんのか。

os.open(devnull, os.O_RDWR)
os.dup(0)
os.dup(0)

85行目

signal.signal(signal.SIGTERM, partial(sigterm, pid))

部分関数使っている。ドキュメントによるとsignal.signalの第二引数は

handler は二つの引数とともに呼び出されます: シグナル番号、および現在のスタックフレーム (None またはフレームオブジェクト

で、部分関数になっているsigtermは以下のように3引数を受け取る関数。第一引数はロックファイル名。

def sigterm(pid, signum, frame):
    logging.info("Caught signal %d. Stopping daemon." % signum)
    os.remove(pid)
    sys.exit(0)