2012年9月30日

Python 3.3.0 リリ-スされた

概要

Python 3.3.0 がリリースされた。
Python 3.3.0 Release

感想

まだ周辺ライブラリが Python 3 に対応していなかったりするので、急いで導入する必要はない。
ただ Python 3.3.0 からは大分導入しやすい感じになってきたので、積極的に新しい物を利用したい人はインストールすると良い。

Python 3.3 の新機能は「Python 3.3 が間もなくリリースされるので新機能を確認しておく」に書いた。ただ、文章だけで、わかりずらいので、再度どっかでそれぞれの機能に関して書いてみたい。

インストール

インストールに難しいことは特に無い。
Python 3.3.0 Release」から自分の環境用のインストーラをダウンロードする。
ActiveTcl」も入れておくと、IDLEやTkinterが使えるのでお勧め。

今月は毎日記事書いてみた

自主的なアウトプット強化月間。
基本は予約投稿で前日に書いたりしているが、ほぼ毎日記事を書いた。
深く記事を書こうとすると時間がかかりすぎるので、書く時間をある程度制限して書いていた。
しかし、記事を書けば書くほど、書きたいことが出てきて、書ききれない。
一度書いた事でも、書きたりなけば、追記でなく別記事にする予定なので、同じような記事を書くかもしれないが、自分用なのであまり気にしないことにした。
すこしペースが落ちるかもしれないが、来月も記事を積極的に書こうと思う。

2012年9月29日

Python で実行時メモリを計測する場合 memory_profiler を利用すると便利

概要

Python でメモリの利用量が知りたい場合、「memory_profiler」を使うと便利。
ライセンスはBSDで、Python 3 にも対応している。

インストール

pip でインストールする。psutilもインストールすると速度が早くなるのでインストールする。

pip install psutil
pip install memory_profiler

使い方

以下の使いかたは、「memory_profiler」に書いてあることそのまま。
計測したいメソッドに「@profile」を付けて、「memory_profiler」を利用して実行する。

sample.py の名前で以下のファイルを作成。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

@profile
def main():
    a = [1] * (10 ** 6)
    b = [2] * (2 * 10 ** 7)
    del b
    return a

if __name__ == '__main__':
    main()

以下のように実行する。

python -m memory_profiler sample.py

出力は以下のようになる。一行ずつ実行した時点でのメモリ総量、メモリ増減量とかを表示する。

Filename: sample.py

Line #    Mem usage    Increment   Line Contents
================================================
     4                             @profile
     5      8.19 MB      0.00 MB   def main():
     6     15.82 MB      7.63 MB       a = [1] * (10 ** 6)
     7    168.41 MB    152.59 MB       b = [2] * (2 * 10 ** 7)
     8     15.82 MB   -152.59 MB       del b
     9     15.82 MB      0.00 MB       return a

ipythonで使う

設定するとipythonから使うことも可能。
「 ~/.ipython/extensions/memory_profiler_ext.py」に以下のファイルを作成。

import memory_profiler

def load_ipython_extension(ip):
    ip.define_magic('mprun', memory_profiler.magic_mprun)
    ip.define_magic('memit', memory_profiler.magic_memit)

「 ~/.ipython/profile_default/ipython_config.py」の該当箇所に以下を追加。

c.TerminalIPythonApp.extensions = [
    'memory_profiler_ext',
]
c.InteractiveShellApp.extensions = [
    'memory_profiler_ext',
]

これを設定することで、ipythonで「python -m memory_profiler」と同じことが「%mprun」で可能になる。
また「%memit」に続けて書くことで、メモリ計測が可能。

その他

ほかにも help で見るといろいろ説明が書いてあるが、このぐらいの機能しか使っていない。今後もうすこし使ってみるかもしれない。

2012年9月28日

Python で実行速度ベンチマークを取る場合は Benchmarker を利用すると便利

概要

Python で実行速度比較を必要とする場合は結構あるが、その場合は「Benchmarker」を使うと便利。
ライセンスが「Public Domain」、Python 3 に対応で機能が多いのに使い易い。

インストール

easy_install を使う。

easy_install Benchmarker

使い方

使い方は結構簡単で最低限必要なのは以下だけ。

  1. Benchmarkerのインスタンスを生成
  2. withブロック内に測定対象コード記述

サンプル

Benchmarker」にサンプルが結構書いてあるが、すこし変えた物を転載しておく。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from benchmarker import Benchmarker


def main():

    s1, s2, s3, s4, s5 = '文字列', '結合', '速度の', '確認を', 'してみる'
    loop = 1000 * 1000
    with Benchmarker(width=20) as bm:
        with bm('join'):
            for _ in xrange(loop):
                _ = ''.join((s1, s2, s3, s4, s5))
        with bm('concat'):
            for _ in xrange(loop):
                _ = s1 + s2 + s3 + s4 + s5
        with bm('format'):
            for _ in xrange(loop):
                _ = '%s%s%s%s%s' % (s1, s2, s3, s4, s5)
        with bm('newformat'):
            for _ in xrange(loop):
                _ = '{}{}{}{}{}'.format(s1, s2, s3, s4, s5)


if __name__ == '__main__':
    main()

まとめ

速度がどうしても必要な時、普段なにげなく利用しているライブラリ等を測定してみると、速度向上に有益な場合がある。
ただ、本当に速度が必要な場合、小手先の変更はあまり意味がない場合もあるので、ベンチマークの結果は参考程度にするのが良いだろう。

2012年9月27日

Mercurial(hg)で無関係なリボジトリをマージする

概要

Mercurial(hg)を利用しいて、無関係なリボジトリをマージしたくなる場合があります。
例えば、リボジトリを二つ作成したが一つの方が適切だったとか、オープンソースのある成果を取り込みたい、等様々な場面が考えられます。
Mercurial(hg)では無関係なリボジトリをマージすることも可能です。

手順

「hg pull -f」のように「-f」を付与するのがポイントです。

mkdir myrepo1
hg init myrepo1
mkdir myrepo2
hg init myrepo2
echo "aaaa" > myrepo1/hello.txt
hg add myrepo1/hello.txt
echo "bbbb" > myrepo2/hello.txt
hg add myrepo2/hello.txt
hg ci myrepo1 -m"myrepo1"
hg ci myrepo2 -m"myrepo2"
cd myrepo1
hg pull -f ../myrepo2
hg heads
hg merge tip

あとは普段のマージ作業と同じになります。

まとめ

無関係なリボジトリをマージできる事を知らないと、そもそもやろうとしないかもしれませんが、これは知っているとかなり便利です。
いろいろ活用範囲があるでしょう。

2012年9月26日

Python に switch-case なんてありません

概要

人にPython教えると switch-case に関してたまに聞かれるのでメモしておく。

ドキュメント

Python で switch-case がない理由は以下のドキュメントにまとまっている。

端的な理由は、switch-caseは綺麗に書けないし、そんなに必要ない、というのが理由。

ではどう書くか

簡単に書く場合は「if-elif-else」で書くか「辞書」で書くのが多い。
以下、とりあえずサンプル。実際にこういう分岐が必要な場合は、もっとオブジェクト指向的に適切な方法を選択するので、あまりこういう記述が出てくるような気がしない。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import unittest


class TestSwitch(unittest.TestCase):

    def test_if(self):
        """if での複数条件分岐"""
        key = 'a'
        if key == 'a':
            print 'a'
            self.assertEqual('a', key)
        elif key == 'b':
            print 'b'
            self.assertEqual('b', key)
        else:
            print 'other'
            self.assertNotIn(('a', 'b'), (key,))

    def test_dict(self):
        """dict での複数条件分岐"""
        key = 'a'

        def key_a(key):
            print 'a'
            self.assertEqual('a', key)

        def key_b(key):
            print 'b'
            self.assertEqual('b', key)

        def key_other(key):
            print 'other'
            self.assertNotIn(('a', 'b'), (key,))

        key_dict = {
            'a': key_a,
            'b': key_b
        }

        key_dict.get(key, key_other)(key)

if __name__ == '__main__':
    unittest.main()

まとめ

どう思うかは好みなので、Pythonはこうだ言うことです。

2012年9月25日

Python でマルチプラットフォームなデスクトップGUIプログラムを作成する場合は Tkinter を使うことにした

概要

Python で マルチプラットフォームなデスクトップGUIアプリ作成する場合は、標準で組みこまれている GUI モジュール Tkinter を使うことに結局おちついたというメモ。

ドキュメント

以下の二つを見ればだいたい理解できる。

サンプル

簡単なサンプル

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import Tkinter
import ttk
root = Tkinter.Tk()
ttk.Button(root, text="Hello World").grid()
root.mainloop()

その他のGUIツールキットに関して

Python で マルチプラットフォームなGUIプログラムを作成するには他にもいろいろある。とりあえず Mac OS X上での開発における個人的な感想は以下。この感想は主眼が Mac 上での動作なので、Linux を主にするなら感想は当然違う。

  • wxPython:いろいろ無茶をするとそれほど頑健ではないが、通常利用ならこまらない。
  • GTK:Mac OS X用のバイナリが配布されていない模様なので、ソースからコンパイルすることになる。いまいちMac上で安定しない。
  • Qt:開発主体がノキアからdigiaに移行して間もないので、現在様子見中。
  • Titanium Desktop:求める機能が上手く実装できない事があった。結構APIに制限がある。今の所利用は保留。

まとめ

マルチプラットフォームで動作するデスクトップGUIを作成する機会は少ないのだが、今回どうしても必要になったので、再びいろいろためしていた。
やや癖はある物の Tk の安定性はかなり良い。
他のが悪いわけではなく、今回の要望に Tkinter が合致した、というただそれだけ。

2012年9月24日

Mac OS X で クロスプラットフォームGUIツールキット Qt を利用してみる

2012/09/24 21時ごろ修正

概要

Qt(キュート)」はノキア digia が開発している、クラスプラットフォームなGUIツールキット。
ライセンスは「GPL」と「LGPL」から選択できる。
Linux で GUI アプリを作成する場合、GTK か Qt を利用することが多い。GTK は Mac 上だといまいちなので、Qt を Mac 上で利用方法を簡単にメモしておく。

注意点

最初からちょっとがっかりだが、Qt は Mac OS X 10.8 Mountain Lion にまだ完全対応していない。10.8対応はもうしばらく待つ必要がある。 4.8.3 から Mac OS X 10.8 に対応した。

インストール

Download Qt for Open Source C++ development on Mac OS X — Qt - A cross-platform application and UI frameworkQt Developer Network」から最新版 dmg をダウンロードする。この記事を書いている時点では「4.8.2」 記事修正時点での最新版は「4.8.3」。

インストール場所の確認

以下のように様々な物がインストールされる。

  • Qt Creator, Qt Designer, Qt Linguist:「/Developer/Applications/Qt」
  • Qt Documentation:「/Developer/Documentation/Qt」
  • Qt Examples:「/Developer/Examples/Qt」
  • Qt Plugins:「/Developer/Applications/Qt/Plugins」
  • Qt Frameworks:「/Library/Frameworks」
  • Qt Libraries:「/usr/lib」
  • qmake, moc, uic, etc.:「/Developer/Tools/Qt (symlink to /usr/bin)」
  • Uninstall script:「/Developer/Tools/uninstall-qtsdk.py」

ドキュメント

Getting Started Programming with Qt | Documentation | Qt Developer Network」とか「Qt Creator」とかを見るとアプリの作成方法が書いてある。

動作確認

動作確認のために簡単なアプリを作成してみる。
Qt Creatorを使うのが本来は簡単だが、ここではソースからビルドしてみる。
以下のようなソースを書く。

#include <QApplication>
#include <QTextEdit>

int main(int argv, char **args)
{
    QApplication app(argv, args);

    QTextEdit textEdit;
    textEdit.show();
    return app.exec();
}

ビルド、起動は Terminal で以下のようにする。

qmake -project
qmake
xcodebuild
open build/Release/sample.app

以下のようにウィンドウが起動する。
文字は後で入力している。
Qt sample

まとめ

簡単にインストールと使い方だけ書いた。
さらに詳細を知りたい場合は、本家のドキュメントがかなり充実しているので、そちらを見ると良い。

2012年9月23日

Sympy を利用して連立方程式(system of equations)を解く

概要

Python の 記号計算ライブラリ「SymPy」を利用して、連立方程式を解いてみる。

連立一次方程式

サンプルとして、以下の三元連立一次方程式を解いてみる。
System of equations

以下のように「solve」を利用して解ける。solve を利用する場合、右辺が0になるように入力する必要がある。 解は dict で出力される。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import unittest

from sympy import (
    Rational,
    solve,
    symbols,
)


class TestSolve(unittest.TestCase):

    def test_system_of_equations(self):
        """連立一次方程式"""
        x, y, z = symbols('x y z')
        self.assertEqual(
            {x: 1, y: -2, z: -2},
            solve([3 * x + 2 * y - z - 1,
                   2 * x - 2 * y + 4 * z + 2,
                   -x + Rational(1, 2) * y - z],
                  [x, y, z]))

if __name__ == '__main__':
    unittest.main()

連立二次方程式

サンプルとして、以下の二元連立二次方程式を解いてみる。
System of quadratic equation

連立一次方程式と同じように解ける。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import unittest

from sympy import (
    solve,
    symbols,
)


class TestSolve(unittest.TestCase):

    def test_system_of_equations(self):
        """連立二次方程式"""
        x, y = symbols('x y')
        self.assertEqual(
            [(-7, 2), (-1, -1)],
            solve([x + 2 * y + 3,
                   x ** 2 + 4 * x * y + y ** 2 + 3 * y - 3],
                  [x, y]))

if __name__ == '__main__':
    unittest.main()

まとめ

連立方程式以外も様々なことができるが、サンプルがすぐに思いつかないので、思いついたらまた書く。

2012年9月22日

Mac OS X で OpenCV 2.4.2 を Python サポート付きでソースからコンパイルする(簡易メモ)

概要

Mac OS X で OpenCV をソースからコンパイルする簡易メモ。

cmake 、その他インストール

CMake - Cross Platform Make」から cmake をダウンロードしてインストールしておく。
OpenCVは依存が結構あるので、「Mac_OS_X_OpenCV_Port - OpenCV Wiki」あたりを参考に入れておく。

Python と numpy のインストル

Python は 自分が利用するバージョンのPython をインストールし、numpy をインストールしておく。

OpenCVのコンパイル

Pythonサポートを正常にコンパイルするには Python 関連のパスを指定して cmake した方が良い。

curl -L http://sourceforge.net/projects/opencvlibrary/files/opencv-unix/2.4.2/OpenCV-2.4.2.tar.bz2/download -o OpenCV-2.4.2.tar.bz2
tar xvfj OpenCV-2.4.2.tar.bz2
cd OpenCV-2.4.2
mkdir build
cd build
cmake -D CMAKE_BUILD_TYPE=RELEASE \
      -D CMAKE_INSTALL_PREFIX=/usr/local \
      -D BUILD_NEW_PYTHON_SUPPORT=ON \
      -D PYTHON_EXECUTABLE=/path/to/bin/python2.7 \
      -D PYTHON_LIBRARY=/Library/Frameworks/Python.framework/Versions/2.7/lib/libpython2.7.dylib \
      -D PYTHON_INCLUDE_PATH=/path/to/include/python2.7 .
make -j2

わたしは都合によりOpenCVを複数バージョン使い分ける必要が出る場合があるので、make install しない。

PYTHONPATHを通す

Python から利用するために、cv2.so があるディレクトリにPYTHONPATH を通す。

export PYTHONPATH=$PYTHONPATH:/path/to/OpenCV-2.4.2/lib

確認

Python を起動して「import cv2」で、import が正常に動作するか確認。「help(cv2)」等してみると良い。

2012年9月21日

Python で記号計算をするためのライブラリ Sympy

概要

「記号計算」とは、代数式のように「x」を利用したり、「cos」などの三角関数、「log」等、「記号」を利用する種類の計算のこと。
Sympy は Python で記号計算をするためのライブラリ。

インストール

インストールは pip 等で行なう。

pip install sympy

ドキュメント

詳細なマニュアルが「SymPy documentation」に存在する。
日本語で概要が説明されている文書が、「2.3. Sympy : Python での記号計算 — Scipy lecture notes」に存在しているので、英語が苦手な人はこちらを読んだ方がわかりやすい。

使ってみる

動作を確認するには分数が簡単。
サンプルは「from sympy import *」が利用されいている場合が多いが、以下のサンプルでは自分の好みで「from sympy import Rational」としている。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import unittest


class TestSymPy(unittest.TestCase):

    def test_rational(self):
        from sympy import Rational
        self.assertEqual(
            '「1 / 2」を Python2 で計算すると「0」になるが、'
            'Sympy の Rational を利用すると「1/2」になる',
            '「1 / 2」を Python2 で計算すると「{elm}」になるが、'
            'Sympy の Rational を利用すると「{rat}」になる'
            .format(elm=1 / 2, rat=Rational(1, 2)))

if __name__ == '__main__':
    unittest.main()

isympy

インタラクティブに計算を実施する場合は、「isympy」コマンドで起動すると良い。ipython をラッピングしたコマンドで、計算結果の出力も工夫される。

LaTex出力

Sympy には LaTeX 数式を出力する機能がある。「latex」メソッドを利用する。

latex(Rational(1, 2))
\frac{1}{2}

まとめ

Sympy は機能が非常に多い。ここで、全機能を解説する時間はないので、マニュアルを読んで必要な機能を自分で探してみると良い。

2012年9月20日

書籍「Think Stats」に出てくる数式(mathematical expression)をLaTeXで書いてみる

概要

書籍「Think Stats」に出てくる数式をいくつかLaTeXで書いてみる。
数式は「LaTeXiT」で確認している。

Think Stats ―プログラマのための統計入門

Think Stats ―プログラマのための統計入門

  • 作者:Allen B. Downey
  • 出版社/メーカー:オライリージャパン
  • 価格:¥ 2,100
  • AmazonAmazon.co.jp(AA)

算術平均

「\mu=\frac{1}{n}\sum_{i}x_i」
Latex mean

分散

「\sigma^2=\frac{1}{n}\sum_{i}(x_i-\mu)^2」
Latex variance

指数分布のCDF

「\operatorname{CDF}(x)=1-e^{-\lambda x}」
Latex dist cdf

指数分布のCDFの補関数(CCDF)

「y \approx e^{-\lambda x}」
Latex dist ccdf

指数分布のCDFの補関数(CCDF)で両辺の対数を取る

「\log y \approx -\lambda x」
Latex dist ccdf log

正規分布の確率密度関数

\operatorname{PDF}_{normal}(x)=
\frac{1}{\sigma \sqrt{2 \pi}} \exp
\begin{bmatrix}
- \frac{1}{2}
\begin{pmatrix}
\frac{x - \mu}{\sigma}
\end{pmatrix}
^2
\end{bmatrix}
Latex pdf

まとめ

LaTeXの数式はかなり簡単に複雑な数式が綺麗に書けて良い。書籍「Think Stats」に出てくる数式はそこまで複雑な物は無いが、かなり高度な数式も書ける。

参考サイト

簡単にLaTeXの数式の書き方を確認したいなら、「Short Math Guide for LaTeX(PDF)」を見るのが一番良い。
日本語ではLaTeXの数式に特化して全てが完結にまとまっているサイトが存在しないように見える。必要に応じていろんなサイトを参照すると良い。

2012年9月19日

Mac OS X で数式(mathematical expression)作成環境構築

概要

数学の勉強をしている場合、Keynote とか Evernote とかに数式を書くために、コンピュータ上で数式を作成したくなる場合がある。
ここでは綺麗な数式を作成するための、数式作成環境を構築する。

LaTeXiTのインストール

Mac OS X で数式作成する場合、「LaTeXiT」を使うと簡単。
ダウンロードしてdmgの中にある「LaTeXiT.app」を「アプリケーション」フォルダに移動。

LaTeXのインストール

LaTeXiT は数式生成に LaTeX のコマンドを利用するので、LaTeX をインストールする。

JIS X0212 for pTeX」から「Drag & Drop UpTeX(UTeX20111010.dmg)」と「ESP Ghostscript 7.07.1(espgs090829.dmg)」をダウンロードする。
「Drag & Drop UpTeX」のdmbの中に「UpTeX.app」があるので、「アプリケーション」フォルダに移動。
「ESP Ghostscript」は「ESPGhostscript.pkg」があるので、これをダブルクリックしてインストール。

X11のインストール

LaTeXiT が利用する gs コマンドが X11 を要求するので、「XQuartz」から dmg をダウンロードし、中にある「XQuartz.pkg」をダブルクリックしてインストールする。

LaTeXiTの設定

LaTeXiT.appを起動する。
LaTeX関連ファイルが見付からないダイアログが出るが、とりあえず全部キャンセル。
Latexit start

「環境設定」の「プログラム」でパスを設定する。
Latexit setting

  • pdfLaTeX:「/Applications/UpTeX.app/teTeX/bin/pdflatex」
  • Ghostscript(gs):「/usr/local/bin/gs」
  • ps2pdf:「/usr/local/bin/ps2pdf」
gs を設定する際に X11 を要求された場合、「アプリケーション」「ユーティリティ」の中に「XQuartz.app」が存在するか確認。存在しない場合は X11のインストールをする。

数式を生成してみる

「y=f(x)」のような簡単な数式を入力して、「LaTeX it!」ボタンを押すと、設定に問題なければ、数式が生成される。
Latexit
数式の部分をドラッグ&ドロップすると保存できる。保存のフォーマットも選択可能。

まとめ

あとは、LaTeXの数式表現を覚える必要がある。
LaTeXの数式はかなり高度な数式を簡単に記述できるし、かなり将来まで使える知識なので、勉強しておいて損はない。

2012年9月18日

高校数学の復習に「カラー版 忘れてしまった高校の数学を復習する本」

概要

統計を人に教える機会があった。教える相手が高校レベルの数学がちゃんとしてないと、どんなに噛み砕いて説明しても理解してもらうのは難しい。また、教える方も補足として高校レベルの数学を教える必要がある場合がある。
統計とか、確立とかをちゃんと理解したければ、高校数学を復習した方が良い。

お勧め書籍

以下の本は、表紙が微妙だが内容は結構ちゃんとしている。高校レベルの数学を全部網羅しているわけではないが、とりあえずこの範囲を知っていると良いのではないだろうか。

カラー版 忘れてしまった高校の数学を復習する本

カラー版 忘れてしまった高校の数学を復習する本

  • 作者:柳谷 晃
  • 出版社/メーカー:中経出版
  • 価格:¥ 1,575
  • AmazonAmazon.co.jp(AA)

まとめ

数学できないと、数学の重要度が理解できない。わかっているつもりにならず、基礎をちゃんと復習すると新しい発見があったりする。

2012年9月17日

iPhone の計算機アプリは横にすると関数電卓になる

概要

iPhone の計算機アプリは結構高機能。ちゃんと機能を使いこなしていない場合もある。

横にすると関数電卓になる

iPhone の計算機アプリは横にすると関数電卓になる。回転ロックしていると気づかないかもしれない。

Iphonecalc tate Iphonecalc yoko

数字部分をスワイプすると1文字入力をキャンセルできる

数字を入れておいて、スワイプするとキャンセルできるのは便利。

まとめ

標準アプリ使いこなしてないのは損。

2012年9月16日

書籍「Think Stats ―プログラマのための統計入門」読んでる

概要

Python でプログラムを書きながら、統計入門する書籍「Think Stats ―プログラマのための統計入門」を読んでいる。
読んでいる目的は、統計を初心者の人に解説する必要が出てきたため、日本語でそれなりにちゃんとした解説を読みたかったから。
この本は、「Think Stats: Probability and Statistics for Programmers」で英語版がオンライン公開されているので、英語でも問題ない人はそれを読んでも良い。

Think Stats ―プログラマのための統計入門

Think Stats ―プログラマのための統計入門

  • 作者:Allen B. Downey
  • 出版社/メーカー:オライリージャパン
  • 価格:¥ 2,100
  • AmazonAmazon.co.jp(AA)

感想

かなり丁寧に解説していて、わかりやすい。人に噛み砕いて説明する場合のヒントが沢山あり、わたしの目的には当っている。
どのレベルを想定するかにもよるが、入門と言ってもちゃんと理解するには高校基礎レベルの数学の知識は必要なので、数学知識がない人は、数学から勉強した方が良いと思われる。

2012年9月15日

Python の文字列フォーマットには format メソッドを利用するべし

概要

Python 2.6 以上を利用しているのに未だに %演算子(モジュロ)を利用した方法で文字列をフォーマットしているサンプルがネットでは出てきますが、はっきりいって古いのでやめましょう。
format メソッドを利用するべし。

format メソッドに関して

PEP 3101 -- Advanced String Formatting」で仕様が定義されている。

サンプル

あまり丁寧ではないが、とりあえずサンプル。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import unittest


class TestStringFormat(unittest.TestCase):

    def test_basic(self):
        """基本的なサンプル
        型を意識しなくても良い
        名前付き指定が可能
        """
        a = 21
        b = 'フルマラソン'
        d = 42.195
        self.assertEqual('21日のフルマラソンは 42.195km です。',
                         '{0}日の{1}は {c}km です。'.format(a, b, c=d))

    def test_object(self):
        """クラスも使える"""
        class SampleModel(object):
            def __init__(self):
                self.id = 1200
                self.name = '永遠'
                self.age = 17

        model = SampleModel()
        self.assertEqual('永遠は17歳',
                         '{model.name}は{model.age}歳'.format(model=model))


if __name__ == '__main__':
    unittest.main()

結論

プログラミング言語は発展しているので、最新の機能は勉強して、利用するとかなり便利だったりする。
不便におもっている事は単に知らないだけ、ということも結構ある。それだと損だと思う。

2012年9月14日

Mac OS X に OpenCV と Python ライブラリを MacPorts を利用してインストールする

概要

OpenCV」と、OpenCV の Pythonライブラリを MacPorts を利用して Mac OS X にインストールする手順。
普段は独自にビルドした物を利用しているが、それなりに面倒なので、MacPorts でインストールするとどんな感じかためしてみる。

OpenCVについて

OpenCV」は「オープンソース(BSDライセンス)のコンピュータビジョン」ライブラリ。
「コンピュータビジョン」とは、雑に説明すれば「コンピュータの視点」ということで、OpenCV はコンピュータに物を見る力を与えるライブラリとなる。

OpenCVには500を越える機能があり、「2次元、3次元画像処理」、「認識、識別」、「情報の表示」等、様々な事ができる。
良くある「肌色率の検出」や「顔認識」なども実装することが可能。
この記事を書いている現在の最新版は、2012年7月4日リリースのバージョン2.4.2となる。

OpenCV の Python ライブラリ

OpenCV は C++ で実装されているが、公式の実装に Python ライブラリが含まれており、ほとんどの機能が Python から利用可能。

インストール

インストールの方法は「いろいろ」ある。ここでは、MacPorts からインストールしてみる。
マシンパワーにもよるが、結構時間がかかる。

sudo port install opencv +python27

インストールディレクトリの確認

以下にインストールされる。cv2.so が本体で、cv.py は 内部で cv2.so を import しているだけのファイル。

/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/cv.py
/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/cv2.so

動作の確認

MacPorts でインストールした場合、MacPorts の Python を利用する。

/opt/local/bin/python2

ライブラリを import する。

import cv
# もしくは
import cv2

機能を確認するには help 関数を利用すると良い。

import cv
help(cv)

とりあえずつかえるようになる。

課題

このままだと MacPorts の Python でしか利用できない。「/opt/local/lib/」以下のファイルに依存した状態で cv2.so がビルドされるので、cv2.so だけコピーして動作するという物でもない。
PYTHONPATHを工夫をすれば良いかもしれないが、独自ビルドした物を普段は利用していてすぐには困らないので、とりあえず保留。

2012年9月13日

Python 画像処理ライブラリ Pillow を使ってみる

概要

Python の画像処理ライブラリはPIL(Python Imaging Library)が有名だが、正式リリースは2009年11月15日にリリースされた1.1.7が最後になっている。
アルファ版の1.2a0が2011年1月8日にBitbucket上でリリースされている(effbot / pil-2009-raclette / downloads — Bitbucket)が、ソースの改修は2011年6月28日で止まっている。

Pillow」は PIL を setuptools 対応にするために fork して開発されているライブラリで、現在も活発にメンテナンスされている。
ただし、PIL も Pillow も正しくは Python 3 に対応していない。Pillowは Python 3対応を徐々にコミットしているようだ。
Pillow」の方が品質が良さげなので、使ってみる。

インストール

Pillow は setuptools 対応しているので PIL と異なりちゃんと pip でインストールできる。
別途、「libjpeg」、「zlib」、「freetype2」、「littleCMS」を事前にインストールしておくこと。

pip install pillow

Windows を利用している人は、shimizukawa / Pillow / downloads — Bitbucketからビルド済みのライブラリをダウンロードすることも可能。

ドキュメント

ドキュメントは「The Python Imaging Library — Pillow」にある。
また、基本APIはPILと同じなので、動作をためす場合、「PIL Tutorial」はかなり役に立つ。

サンプル

画像処理をする場合のサンプル画像は「SIPI Image Database」から持ってくるのが良い。
おそらくこの手の画像で一番有名なのが、「Lena, or Lenna」の画像だろう。
Pillowのレポジトリ(Pillow/Images at master · python-imaging/Pillow · GitHub)にも存在している。

本当に簡単なサンプルを以下に示す。PIL と使い方に違いはない。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import unittest

import Image


class TestPillow(unittest.TestCase):

    def setUp(self):
        self.image = Image.open('lena.ppm')

    def test_open(self):
        """画像を開く"""
        self.assertEqual('PPM', self.image.format)
        self.assertEqual((128, 128), self.image.size)
        self.assertEqual('RGB', self.image.mode)

    def test_tojpeg(self):
        """画像を リサイズして JPEG に変換"""
        small = self.image.resize([32, 32])
        small.save('lena_small.jpg', 'JPEG')

if __name__ == '__main__':
    unittest.main()

まとめ

画像を簡単に処理する Python のライブラリ Pillow を使ってみた。画像処理はちょっとした時に必要になるので、覚えておいて損はない。

2012年9月12日

py.test で pep8 と coverage を同時にチェックする

概要

Python で テストする場合、pytestを使うと便利だ。
pytest には plugin 機構が存在しており、pep8 と coverage を同時にチェックすることができる。

設定

特に設定する項目はなく、plugin を pip でインストールするだけで使うことが可能になる。

pip install pytest-pep8
pip install pytest-cov

実行

py.test の実行にに、オプションに「--pep8」を付けると pep8 チェック、「--conv」を付けると coverage が動作する。

py.test --pep8 --cov myproj -v tests

pep8 チェックと coverage チェックが表示される。coverage チェックは毎回実行する必要はないが、pep8はチェックしておいた方が良い。

============================= test session starts ==============================
platform darwin -- Python 2.7.3 -- pytest-2.2.4 -- /path/to/bin/python
cachedir: /path/to/myproj/.cache
collected 3 items 

tests/__init__.py:0: PEP8-check SKIPPED
tests/test_sample.py:0: PEP8-check PASSED
tests/test_sample.py:15: TestSample.test_sample PASSED
--------------- coverage: platform darwin, python 2.7.3-final-0 ----------------
Name                  Stmts   Miss  Cover
-----------------------------------------
myproj/__init__        1      0   100%
myproj/sample          8      0   100%
myproj/sample2         8      3    63%
-----------------------------------------
TOTAL                  17      3    82%

===================== 2 passed, 1 skipped in 0.27 seconds ======================

テスト、テスト、そしてテスト

テストを書く。テストは最初に書く必要はないが、かならず必要になる。

2012年9月11日

Python 3.3 が間もなくリリースされるので新機能を確認しておく

概要

Python 3.3 安定版が今月中にリリースされる予定。すでに rc2 までリリースされているので、新機能を確認しておこうと思う。

新機能の確認

What’s New In Python 3.3」で新機能が確認できる。
まだ、良く理解してない機能もある。機能が多すぎて全部は無理なので、とりあえず上からメモしておく。以下のメモは正しさは一切保証しない。

Virtual Environments

「virtualenv」として存在した、Pythonの環境を切り分ける機能と同等の物が「venv」機能として実装された。「pyvenv」コマンドがインストールされるので、「pyvenv」コマンドを利用するのが簡単そう。
本当はパッケージ管理ツールの「pysetup」も入るはずだったのだけど、品質が向上しなかったり等で今回は外された。正直「pysetup」がはいってない「pyvenv」だけだといまいちな印象になってしまっている。

Namespace Packages

Pythonでパッケージを作成するにはディレクトリ内に「__init__.py」を用意する必要があったが、不要になった。
Python 3 は Python 2 と import の動作が異なるので注意。

New memoryview implementation and buffer protocol documentation

Python 3 では buffer() が memoryview() に変更されて、かなりいろいろ変更されている。

Flexible String Representation

文字列は完全に UCS-4 対応している。文字列表現は Python 3.2 まではちょっと厳密すぎたのだけど、すこし緩くなった。

Reworking the OS and IO exception hierarchy

OS と IO の例外階層が整理されている。綺麗になってデバッグしやすい等、便利。

Syntax for Delegating to a Subgenerator

「yield from」が追加されて、これはとても便利。というか、この手の機能を必要とする人にはめちゃくちゃ便利。

Suppressing exception context

例外の中で例外出すときに「raise from」文法が追加されている。

Explicit Unicode literals

Python 2 では u'xxx' みたいにして Unicode literals を明示していたが、Python 3.2 までは明示せずに Unicode literals になったので u'xxx' の機能がなかった。Python 3.3 では u'xxx' 表現が復活、でも付けてもたいした意味はない。Python 2 との互換性維持等が目的。
地味に Python 2 でも Python 3 でも動作するソース作成しようとすると面倒だったので、この改善は良いと思う。

Qualified name for classes and functions

class と function にQualified name(修飾名)を取得できる「__qualname__」が増えた。

Key-Sharing Dictionary

いろいろと細かい事はあるのだけど、組み込みの dict(辞書)のメモリ効率が良くなり、早くなったと思っておけば良いような。

Function Signature Object

functionのシグニチャがオブジェクトになっている。「inspect.signature()」メソッドが増えたりしている。
かなり便利なのだけど、どのぐらいの人がこの機能を使うのかわからない。

Adding sys.implementation

「sys」モジュールに「sys.implementation」が増えた。

lzma

lzma に標準で対応した。bz2 も修正されている。

まとめ

機能が多すぎて力つきた。理解してない機能があるけど、手元の Python 2 でしか動作しない自作モジュールとかを移植しながら勉強しようと思う。

2012年9月10日

Python OAuth ライブラリ rauth で Twitter API v1.1 を利用する

概要

Twitter API v1.1 が公開されました。 全ての endpoint で OAuth 1.0a での認証が必須になっています。
Python のライブラリで OAuth 1.0aの認証が簡単にコーディングできる「rauth」から、Twitter API v1.1 を利用してみます。

rauth に関して

rauth」は OAuth 1.0/a, 2.0、Oflyの認証に対応した Python のライブラリです。
Python の HTTPライブラリである「requests」に依存しています。
requests」が非常にすぐれたライブラリで、その機能を有効に利用しているため、「rauth」はかなり簡単に OAuth 認証のコーディングが可能です。
ライセンスは MIT ライセンスです。残念ながら Python 3 には現在対応していない模様です。

インストール

pip でインストールします。

pip install rauth

rauth は「requests」に依存していますが、pip なら依存関係を解決してインストールされます。

Twitter API v1.1 にアクセスしてみる

「access_token」、「access_token_secret」は取得済みの状態とします。
以下は、「search/tweets」の「application/rate_limit_status」を取得するサンプルです。unittest として記述しています。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import unittest

from rauth.service import OAuth1Service


class TestApi(unittest.TestCase):
    """Twitter API test"""

    def test_oauth(self):
        auth = OAuth1Service(
            name='twitter',
            consumer_key='consumer_key',
            consumer_secret='consumer_secret',
            request_token_url='https://api.twitter.com/oauth/request_token',
            access_token_url='https://api.twitter.com/oauth/access_token',
            authorize_url='https://api.twitter.com/oauth/authorize')
        self.assertIsNotNone(auth)
        response = auth.get(
            'https://api.twitter.com/1.1/application/rate_limit_status.json',
            access_token='access_token',
            access_token_secret='access_token_secret')
        content = response.content
        limit = content['resources']['search']['/search/tweets']['limit']
        self.assertEqual(180, limit)

if __name__ == '__main__':
    unittest.main()

つぶやいてみる

つぶやきを投稿するサンプルは以下になります。「application/rate_limit_status」の例を含めて多少汎用化してあります。Python 2.6、Python 2.7 で動作します。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import unittest

import datetime

from rauth.service import OAuth1Service


class TestApi(unittest.TestCase):
    """Twitter API test"""
    def setUp(self):
        self.auth = OAuth1Service(
            name='twitter',
            consumer_key='consumer_key',
            consumer_secret='consumer_secret',
            request_token_url='https://api.twitter.com/oauth/request_token',
            access_token_url='https://api.twitter.com/oauth/access_token',
            authorize_url='https://api.twitter.com/oauth/authorize',
            header_auth=True)
        self.access_token = {
            'access_token': 'access_token',
            'access_token_secret': 'access_token_secret'}
        self.endpoint = 'https://api.twitter.com/1.1/{path}.json'

    def test_get_rate_limit_status(self):
        """application/rate_limit_status test"""
        response = self.auth.get(
            self.endpoint.format(path='application/rate_limit_status'),
            **self.access_token)
        content = response.content
        limit = content['resources']['search']['/search/tweets']['limit']
        self.assertEqual(180, limit)

    def test_post_statuses_update(self):
        """statuses/update test"""
        text = 'つぶやきテストです。{now}'.format(now=datetime.datetime.now())
        params = {'status': text}
        response = self.auth.post(
            self.endpoint.format(path='statuses/update'),
            params=params,
            **self.access_token)
        content = response.content
        self.assertEqual(text.decode('utf-8'), content['text'])

if __name__ == '__main__':
    unittest.main()

まとめ

rauth」で Twitter API v1.1 を利用して、情報の取得と投稿ができました。Twitter API v1.1 がかなり整理されたことで、簡単な処理なら Twitter に特化したライブラリを利用する必要はほとんどないかもしれません。
rauth」は Twitter だけでなく OAuth 認証全般で利用できますので、試してみると良いでしょう。

2012年9月9日

Twitter API v1.1 を確認する

概要

2012年9月5日にTwitter社が API v1.1 の詳細を公開したので、確認してみます。

関連する文書

関連する文書は以下となります。

API v1.1の概要

Overview: Version 1.1 of the Twitter API | Twitter Developers」に概要が記述されています。

  • 各endpoint毎に15分毎の呼出回数制限が設定された。ほとんどが15分15回で、検索系APIのみ15分180回。発言も15分180回。
  • JSONだけになった。XMLやRSSは提供されない。
  • 全てのendpointでOAuth認証が必須になった。
  • つぶやきの表示形式が義務付けられた。
  • 10万を越えるユーザを抱えるクライアントは、それ以上ユーザを増やすには申請が必要。
  • API v1.0 は 2013年3月5日に停止される。
  • dev.twitter.com の文書は、v1.1用に更新される。
  • 意見はまだ募集しており、今後変更される可能性はある。

その他変更されたと思われる部分

まだ、十分さわれていないが、概要に書いていない部分で変更点がある模様。

  • 認証しないでアクセスした場合のHTTPステータスコードが v1.0 と異なる。v1.0 では 「400 Unauthorized」で、v1.1 では 「401 Bad Request」。
  • Streaming API の機能が増えて、よりリアルタイム性が増した。

個人的な意見

個人的な意見を書いておく。Twitter社には比較的同情的な立場。Twitter も比較的普通の使い方しかしてないと思われる。

  • REST API v1.1 Resources | Twitter Developers」を見ると非常に良く設計されたAPIだと感じる。かなりいろいろな事を考慮して作成されている。
  • v1.0 から v1.1 への移行は比較的容易になるように考慮されている。
  • 「認証」を前提とした設計になっていると強く感じる。
  • XML、RSS が提供されなくなるのは「認証」を前提とした時はある意味必然の結果に見える。
  • APIの制限が、v1.0は全てを合計して 350回/時 だったのが、v1.1 では endpoint 毎に 15回/15分や、180回/15分になったことで、おそらく API はより安定すると思われる。
  • 多くの人はタイムライン取得を1分に1回にしており(多くのついったクライアントのデフォルト値)、ほとんどの人がAPI制限にひかからない。むしろ増えたように感じるだろう。
  • 1分に1回以上タイムラインを取得したい場合は、Streaming API の user endpointを利用すれば可能。
  • モバイルに関しては iPhone/Android 以外はほとんど考慮していないと思われるが、普通の使い方の限り iPhone/Android でもあまり問題が無いように見える。iPhone/Android 上でも Streaming API は当然利用できる。
  • つぶやきの表示義務(Developer Display Requirements | Twitter Developers)は、必要な情報をちゃんと全部表示しろ、という義務に見える。
  • つぶやきの表示義務はTwitter公式クライアントも守れているのか怪しい。ちょっとおかしい感じ。
  • クライアントのユーザ10万制限は、Twitter側のインフラがそろそろ限界なのだろう。また、ほとんどのクライアントは10万いかず、10万を越えるほどのクライアントなら、申請すればちゃんと通るのではないか、と楽観的に考えている。
  • ヘビーユーザは、そろそろ別のサービスに移動する時期なのではないだろうか。Twitter 側はそれを認識しているように見える。
  • APIの設計から考えるに、Twitter 社は今回の決定をいかなる反対があっても断固として実行すると思われる。Twitter社はある意味おいつめられている感じがする。
  • API v1.1になっても依然として、「完全な」クライアントを作成することが可能な時点で、他の企業と比較しても明らかに異状な API 公開態度に見える。
  • 移行期限が長いか短いかで考えると、短い感じもするが、おそらく、年度をまたぐような延長は無いと思われる。3/5 という期限は非常に考慮してある感じだ。
  • 今回の件でクライアントの一部が開発を終了したり、ユーザに混乱が発生するだろうが、ほとんどは時間が解決するだろう。
  • ユーザが騒いでも、Twitter社にとってはほとんど問題にならない規模だろう。

まとめ

変な所には意見を言うべきかと思う。
ただ、全体的に良くできているため、最終的には、ヘビーユーザの一部が離れ、クライアントが整理され、botが多少減り、一般ユーザはあまり困らない、という結果になるのでやないか、と今の所は楽観視している。

2012年9月8日

Python 3.3 移行するならテスト環境を py.test と tox にすると便利

概要

予定通りに行けば、Python 3.3 が今月中にリリースされます。
現在は Python2 と Python3 は移行時期で、完全に Python3 に移行するのは難しいタイミングです。しかし、将来確実に Python3 に移行する必要が出てくるため、場合によっては、Python2 と Python3 両方で動作するソースを作成する必要があります。
Python2 と Python3 で動作するソースを書く場合、別バージョンのPythonで同じソースを同時にテストできる「tox」と、テスト結果を詳細に表示してくれる「pytest」を導入すると便利になります。

インストール

pip でインストールできます。

pip install tox
pip install pytest

また、複数のバージョンのPythonでテストする場合は、環境に該当バージョンのPythonをインストールする必要があります。

準備

tox でテストを動作させるには最低限 setup.py と tox.ini が必要です。

まずは setup.py を用意します。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from setuptools import setup

setup(
    name='sample',
    version='0.0.1',
)

まずは tox.ini を用意します。

# tox.ini
[tox]
envlist =
    py26,
    py27,
    py32,
    py33,

[testenv]
deps = pytest
comands = py.test -v tests

実行

実行は tox コマンドで実行できます。

tox

エラーが出た場合の対処

エラーが発生した場合、toxを実行したディレクトリ直下に「.tox/log」が生成されて、ログが出力されます。
ログは比較的詳細に出力されますので、これを見ることで問題を解決することができるでしょう。

Mac OS X の特定の環境では readline 関連のエラーが出るようです。

AssertionError: Filename /path/to/python2.7/site-packages/readline.so 
      does not start with any of these prefixes

エラー発生箇所のreadline.soをリネームしておくと発生しなくなります。

cd /path/to/python2.7/site-packages/
mv readline.so readline.so-bak

環境によっては tox に関係の無いエラーが発生してしまう場合がありますが、log の出力が結構しっかりしているので、対処は可能ではないかと思います。

テストを書きましょう

あとは、テストを書きましょう。

Python で URL 操作にしたい場合は furl を利用する

概要

Python 標準の urllib 等を利用した URL 操作は結構面倒。URL パラメータとかを生成する場合等は furl を利用するのが便利。

インストール

pip を利用する。

pip install furl

使い方

使い方は「furl/API.md」に全部書いてある。

サンプル

これだけだとつまらないので、ほんの一部の機能を使った簡単なサンプルをはっておく。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import unittest

from furl import furl


class TestFurl(unittest.TestCase):

    def setUp(self):
        """
        気象庁 東京 2012年8月データを取得する URL をサンプルにする
        """
        self.url = furl(
            'http://www.data.jma.go.jp/obd/stats/etrn/view/daily_s1.php?'
            'prec_no=44&'
            'block_no=47662&'
            'year=2012&'
            'month=8&'
            'day=&'
            'view=')

    def test_change_year(self):
        """
        年を変更してみる
        """
        #  年を変更する
        self.url.args['year'] = '2011'
        self.assertEquals(
            'http://www.data.jma.go.jp/obd/stats/etrn/view/daily_s1.php?'
            'prec_no=44&'
            'block_no=47662&'
            'year=2011&'  # 年が変更された
            'month=8&'
            'day=&'
            'view=',
            self.url.url)

    def test_clear(self):
        """
        パラメータをクリアする
        """
        self.url.set({})
        self.assertEquals(
            'http://www.data.jma.go.jp/obd/stats/etrn/view/daily_s1.php',
            self.url.url)

if __name__ == '__main__':
    unittest.main()

課題

furl は現在 Python3 に対応してない。パッチは投稿されているみたいなので、対応をすこし待ってみる。
もし Python 3 に対応しないようなら、fork してでも使いたいライブラリです。

2012年9月7日

Python で pep-8 の「E501 line too long」にしないためのコーディングテクニック

概要

Python は 「PEP 8 -- Style Guide for Python Code」というコーディング規約がある。
また、ソースコードが pep-8 に準拠しているかチェックするための「pep8 - Python style guide checker」が存在する。
Python 使いは、pep-8 に準拠したソースを記述するのが良い。

pep-8 の中で最も守られていないルールはおそらく「1行79文字制限」ではないだろうか。
pep8 - Python style guide checkerではこれに違反すると「E501 line too long」になる。

テストコード等一部で E501 になるのが仕方ない場合もあるが、通常 E501 が出るのは避けるべきだ。
E501 を避けるためのテクニックを紹介する。

テクニックのポイント

Pythonが丸括弧「()」で囲んだ範囲を纒まりとして認識することを利用する。

長い文字列の改行

URLなどは長い文字列になりがちだ。

sample = 'http://www.data.jma.go.jp/obd/stats/etrn/view/daily_s1.php?prec_no=44&block_no=47662&year=2012&month=8&day=&view='

長い文字列は以下のようにすれば改行できる。

sample = ('http://www.data.jma.go.jp/obd/stats/etrn/view/daily_s1.php?'
          'prec_no=44&block_no=47662&year=2012&month=8&day=&view=')

Python は「()」で囲んだ中は一つの連続として取り扱い、かつ「()」内で連続した文字列を自動で結合する。
この場合「+」演算子で結合したり、「format」や「%s」を利用する必要はない。

以下は極端に改行した例だ。

sample = ('http://www.data.jma.go.jp/obd/stats/etrn/view/daily_s1.php?'
          'prec_no=44&'
          'block_no=47662&'
          'year=2012&'
          'month=8&'
          'day=&view=')

当然改行しても、format や %s 等は正常に動作する。

%s を利用した例。

sample = ('http://www.data.jma.go.jp/obd/stats/etrn/view/daily_s1.php?'
          'prec_no=%s&block_no=%s&year=%s&month=8&day=&view='
          % (44, 47662, 2012))

format を利用した例。

sample = ('http://www.data.jma.go.jp/obd/stats/etrn/view/daily_s1.php?'
          'prec_no={}&block_no={}&year={}&month=8&day=&view='
          .format(44, 47662, 2012))

これで横 79文字制限を避けることができる。

複数 import 文の改行

import 文に「*」を使わないようにすると、複数の import 文だと横に長くなる場合がある。

from mongoengine import BooleanField, DecimalField, DateTimeField, EmbeddedDocumentField, StringField

文字列の場合と同様「()」を利用することで、改行が可能だ。

from mongoengine import (
    BooleanField,
    DecimalField,
    DateTimeField,
    EmbeddedDocumentField,
    StringField,
)

メソッド呼びだしなどが長い場合の改行

メソッドの中でメソッドを呼び出すと、横に長くなる傾向がある。

sample_function(foo_function(bar_function('test')))

以下のように改行できる。

sample_function(
    foo_function(
        bar_function('test')))

ただ、このようなコーディングは本来は避けた方が良いだろう。

1行79文字を越えるのは設計かコーディングが変だと考えること

文字列やimport文以外で、1行79文字を越えなければいけないのは完全にコーディングがおかしい。
引数が多すぎるメソッドやメソッドの中でメソッドの呼び出しはオブジェクト指向を理解しているとは言いがたいコーディングである。
1行79文字を越えた場合、おかしい、と考えるべき。

結論

pep-8 は非常に良く考えられたコーディング規約だ。完全準拠したコーディングを愚直に実施してみると、その真の意味が理解できるようになるだろう。

2012年9月6日

pyquery で XML の namespace を扱う

概要

pyquery は XML を JQuery のように処理するこができる。
XML の namespace も処理することができる。

処理するXML

pypi は 各パッケージに DOAP(Description of a Project) が提供されているので、サンプルとしてこれを処理する。
pyquery 1.2.1 の DOAP は http://pypi.python.org/pypi?:action=doap&name=pyquery&version=1.2.1になる。

DOAP の形式確認

DOAP は RDF で、pypi の DOAP は以下のような形式になっている。

<?xml version="1.0" encoding="UTF-8" ?>
<rdf:RDF xmlns="http://usefulinc.com/ns/doap#"
         xmlns:foaf="http://xmlns.com/foaf/0.1/"
         xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<Project>
<name></name>
<shortdesc></shortdesc>
<description></description>
<homepage></<homepage>
<maintainer>
<foaf:Person>
<foaf:name></foaf:name>
<foaf:mbox_sha1sum></foaf:mbox_sha1sum>
</foaf:Person>
</maintainer>
<release><Version><revision></revision></Version></release>
</Project></rdf:RDF>

サンプル

revisionの中身を取るには以下のようにする。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from pyquery import PyQuery as pq


def main():
    url = 'http://pypi.python.org/pypi?:action=doap&name=pyquery&version=1.2.1'

    # namespace
    namespaces = {"ns": "http://usefulinc.com/ns/doap#"}
    # pyquery
    query = pq(url, parser='xml')

    # revision の取得
    revision = query('ns|revision',
                     namespaces=namespaces).text()

    print revision


if __name__ == '__main__':
    main()

どうやって調べるのか

Python 系のパッケージはだいたいテストソースが付いている。
pyquery のテストソースには namespace の処理例が書いてある。
namespace の処理以外にも pyquery で可能な処理がほとんど書いてあるので、テストソースを読むと大体の事は解決する。

2012年9月5日

pyquery を利用して気象庁のWebサイトから過去の気象データを取得する

概要

pyqueryを利用してスクレイピングをする。
気象庁のWebサイトから過去の気象データを取ってみる。

注意点

スクレイピングは相手サーバに負荷をかけないように注意すること。この記事を参考にして、問題が発生しても一切責任は取らない。自己責任でどうぞ。

pyquery について

jQuery 風にHTML/XML が操作できるのが特徴。パーサーに lxml を利用するのでパース速度も高速で、lxml に可能なことは、大体可能。
この分野だと、beautifulsoupも有名。pyqueryとどちらを利用するかは好みの問題。

pyquery のインストール

pip でインストールできる。lxml に依存している。

pip install pyquery

サンプルソース

2012年8月の東京の平均気温を取得するサンプル。
以下のサンプルはまったく汎用的にしてないが、jQueryを知っていればかなり簡単。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from pyquery import PyQuery as pq


def main():
    # 気象庁 東京 2012年8月データ
    url = ('http://www.data.jma.go.jp/obd/stats/etrn/view/daily_s1.php?'
           'prec_no=44&block_no=47662&year=2012&month=8&day=&view=')
    #  pyquery
    query = pq(url, parser='html')
    # title の取得
    title = query('title').text()
    # 日毎を取得
    day = query('.data_0_0')

    print title
    for i, item in enumerate(day):
        if i % 20 == 5:
            print('{:02d}日の平均気温 {} ℃'
                  .format(i / 20 + 1, pq(item).text()))

if __name__ == '__main__':
    main()

2012年9月4日

Emacs での Python コーディングに python-mode.el でも標準の python.el でもない python.el を使ってみている

概要

Emacs 上で Python をコーディングする場合のモードはどれを使うのが良いのかを再検討中。

モードの候補

EmacsでPythonコーディングをする場合、複数のモードが存在する。
以下の3つが選択肢になる。

Emacs 標準の python.el は大分良くなってきたが、機能がちょと不足している。また、自動インデントが pep-8 に対応していない部分がある。

長い間python-mode.el in Launchpadを利用してきたが、補完関連は非常に強力なのだが、やはり自動インデントが pep-8 にちゃんと対応していない部分がある。

インデントが一番意図通りに動作するのが fgallina/python.el · GitHubだったので、これを利用してみている。

設定

本日時点では以下のような設定にしている。補完は iPython 上でやってしまうため、今の所補完関連の設定はしているが、ちゃんと動作していない。

おためし中

もうしばらく利用してみて、python-mode から完全に移行するか検討する。

2012年9月3日

ps の出力を grep する時「grep -v grep」しないで grep 自身のプロセスを取り除くには "[プ]ロセス名"

概要

psの出力をgrepする場合、grep 自身が含まれる。取り除く場合「grep -v grep」を利用するが他の方法もある。

"[プ]ロセス名"

zsh のプロセスを grep する場合は以下のようにする。

ps aux | grep "[z]sh"

簡単な解説

[ ] は囲まれた文字のリスト中の一文字にマッチする。
「grep "[z]sh"」とダブルクォートで囲み[ ]を使うことで grep の プロセスは「grep "[z]sh"」になる。
実際のプロセスの検索は「z」一文字と「sh」という意味で検索されるため、grep のプロセスは一致しなくなる。

課題

これは手で grep する時用な気がしている。スクリプトの中で grep 対象が変数に格納されている場合は「grep -v grep」の方が書くのは楽。

元ネタ

結構昔から利用しているので元ネタはすっかり忘れたが、おそらく元ネタはこのあたり。ps -ef | grep hoge | grep -v grep ではなく、ps -ef | grep [h]oge - hogehoge @teramako

2012年9月2日

OS X で tmux のバッファをクリップボードでも使う

概要

OS X で tmux を利用していると tmux のバッファをクリップボードでも使いたくなる。 tmux の標準機能にはないので、設定する。

設定

OS X の tmux のバッファをクリップボードでも使えるようにするソースがGitHubで開発されている。
ChrisJohnsen/tmux-MacOSX-pasteboard · GitHub

マニュアル通りにコンパイルしても良いが MacPorts や homebrew でもインストールできる。

MacPortsの場合

sudo port install tmux-pasteboard

homebrewの場合

brew install reattach-to-user-namespace

tmux.confは以下のように記述する。

set -g default-command "reattach-to-user-namespace -l zsh"
unbind ^y
bind ^y run "tmux save-buffer - | reattach-to-user-namespace pbcopy"
unbind ^p
bind ^p run "reattach-to-user-namespace pbpaste | tmux load-buffer - && tmux paste-buffer"

残課題

この設定だと Mac と Linux で tmux.conf を共有する場合は工夫しないとだめそう。

2012年9月1日

Emacs 24 の Emacs Lisp スクリプトで shebang を書いても Lexical Scope を有効にする方法がわからない(解決)

概要

Emacs Lisp は Emacs 24 から Lexical Scope が利用できるので、コマンドラインスクリプトが書き易くなった。
Emacs 使いはこの際、スクリプトを Emacs Lisp で書けば良いのぢゃないかと思った。
でも、shebang を書いて実行すると Lexical Scopeが有効にならないみたい。

普通にスクリプトとして実行

Emacs では Emacs Lisp をスクリプトとして実行できる。

;; -*- coding: utf-8; lexical-binding: t -*-
(message "hello world")
以下で実行する。
emacs --script sample.el

shebangを利用できるか

「emacs --script」で起動するのでなく普通にスクリプトとして起動したい。

chmod 755 sample.el
./sample.el

でも、「shebang」(シバン or シェバン)(!#) を書くと Lexical Scope が有効にならない。

#!/usr/bin/env emacs --script # -*- coding: utf-8; lexical-binding: t -*-
;; これは正常に動作しない。 2番目の # 以降が無視される。
;; 2番目の # を先頭にすると shebang が無視される。
;; 2番目の # を ;;; とかに変更すると文法エラーになる。

以下のように書いても Lexical Scope が有効にならない。

:;exec emacs -batch -l "$0" "$@" --no-site-file -q  # -*- coding: utf-8; lexical-binding: t -*-

知りたいこと

ソースまで調べていないので、shebangの利用をしながら Lexical Scope が有効にできるか不明。
「emacs --script」で起動すれば良いので、困るわけではないが、なんか方法があるなら知りたい。

補足:Emacs Lisp でコマンドラインスクリプトを作成する

Emacs Lisp でコマンドラインスクリプトを作成したい方は、「スクリプト言語としてのEmacs Lisp」を参照するとわかりやすい。

追記

2012年09月01日深夜追記

cvmat@twitterからの指摘。
GNU Emacs Lisp Reference Manual 11.9.4 Using Lexical Binding」に「Note that unlike other such variables, this one must be set in the first line of a file. 」の記述があり、1行目にしか書けない。
1行目に書くパターンでも shebang を書いた状態で認識させる方法が無いみたい。
現在の仕様では無理みたい。

2012年09月01日深夜さらに追記

cvmat@twitterから「exec」で「/dev/stdin」を使う方法を教わりましたので以下みたいにしたら動作しました。
安全かどうかとか、これが綺麗な書き方かとかはまだ詳細に考えていませんが動かす方法があることはわかりました。ありがとうございます。

:;exec emacs --script /dev/stdin <<EOF
;; -*- coding: utf-8; lexical-binding: t -*-
(setq x 1)
(defvar y 2)

(defun one ()
  (message "one: x = %d, y = %d" x y)  ;; x = 1, y = 5
  (+ x y))

(defun two ()
  (message "two: x = %d, y = %d" x y)  ;; x = 1, y = 2
  (let ((x 3)
        (y 5))
    (one)))

(message "%d" (two))  ;; 6 が表示される(x = 1, y = 5の加算)
;:EOF