2015/01/27

Python Tips:ワンライナーが書きたい

Pythonでワンライナーコマンドを書く方法をご紹介します。

Pythonでワンライナーを書くには c オプションを使います。
python -c "print("hello world")"
# hello world と出力される
ヘルプドキュメントによると、 c は cmd の c だとか。個人的にはc というのはあまり直感的でなくて覚えにくい気が、します。。

引数を扱いたい場合には sys.argv を使います。
python -c "import sys; print(sys.argv)" a b c def
# ['-c', 'a', 'b', 'c', 'def'] と出力される

sys.argv を使えば、たとえば、引数の合計値を計算することなんかもできます。
python -c "import sys; print(sum([int(x) for x in sys.argv[1:]]))" 3 4 5
# 合計の 12 が出力される

また、標準入力を扱いたい場合には input() もしくは sys.stdin.read() を使います。
hayato:Desktop$ pwd | python -c "import sys; print(input().split('/'))"
# カレントディレクトリを構成するディレクトリが配列に分割されて表示される

以上です。


・・・ということで、ほんの数例を見てみただけでも、Pythonのワンライナーというのはあまり使い勝手がよい感じではないことがよくわかります笑

他のスクリプト言語のワンライナーや他のコマンドなんかも比べてみても、あえてPythonでワンライナーを書きたくなる場面というのは、あまり多くはなさそうです。

ちなみに、ワンライナーといっても、上で見たようなコードを直接渡すものではなく、モジュールを利用する形のものであれば、使い途はたくさんあるようです。こちらのページに良い例がいくつか紹介されていますのでよろしければ覗いてみてください。
# jsonを整形するなら
$ echo '{"foo": "lorem", "bar": "ipsum"}' | python -mjson.tool
# 簡易ウェブサーバを走らせるなら
$ python -m SimpleHTTPServer


参考
Powerful Python One-Liners - Python Wiki
Python command line oneliners

2015/01/20

ライブラリ:selenium

Python の「 selenium 」というライブラリをご紹介します。

import selenium

selenium ライブラリは、同名の Selenium というブラウザ操作用のツールがあるのですが、その Python バインディング、いわゆる「 Selenium の Python 版」です。

selenium ライブラリを使うことで Firefox などのブラウザを Python からかんたんに操作できるようになります。

以下、使い方をかんたんに見ていきます。まずはインストールから。


インストール

pip が入っていれば、他のライブラリと同じように pip install でインストールすることができます。
pip install selenium

Mac 環境だとこの形でインストールできますが、 Windows 環境では少し異なるかもしれません。 Python 以外の情報も含む Selenium 全体の公式ダウンロードページはこちらになります。
- Downloads - Selenium


使い方

基本的な使い方を見ていきます。

最小単位は次のような形になるでしょうか。
# ライブラリの読み込み
from selenium import webdriver

# ドライバの生成
# 問題なければFirefoxブラウザが自動的に起動する
driver = webdriver.Firefox()

# Firefox上でURLを指定してGETリクエスト
driver.get("http://www.google.co.jp/")

# ドライバを閉じる
# 問題なければFirefoxも終了する
driver.close()

ブラウザを開いて、特定のページを開いて、ブラウザを閉じる、という一連の流れがこれだけのコードで実現できます。

ちなみに、 selenium ではブラウザを操作するインスタンスを「ドライバ」と読んでいます。デフォルトで使えるのは Firefox ですが、Firefox のほかにも Chrome Safari PhantomJS IE など主要なブラウザを操作するドライバがサードパーティ製で公開されているので、適宜インストールすれば使うことができるようになります。

上の例ではページを開いて閉じただけであまりおもしろみがないので、キーボード操作をするような例についても見てみたいと思います。

こちらは公式ドキュメントの例にコメントをつけたものになります。
# ライブラリの読み込み
# Keys はキーボード操作に相当するモジュール
from selenium import webdriver
from selenium.webdriver.common.keys import Keys

# ドライバの生成
# Firefoxを起動させる
driver = webdriver.Firefox()

# FirefoxでGETリクエスト
driver.get("http://www.python.org")

# 期待どおりのページが開かれたことを確認するアサーション
assert "Python" in driver.title

# ページ内のHTML要素をname属性を使って取得
# name属性の値が q である要素が選択される
elem = driver.find_element_by_name("q")

# 選択した要素に対してキーボード入力
# selenium という文字を入力し、リターンキーを押す
elem.send_keys("selenium")
elem.send_keys(Keys.RETURN)

# 期待どおりのページが開かれたことを確認するアサーション
assert "Google" in driver.title

# ドライバを閉じる
# Firefoxも終了する
driver.close()

コードの各文の意味合いはコメントに書いてあるとおりです。

このコードを走らせてみると、ブラウザがひとりでにウニョウニョ動く様子を確認することができます。

以上です。


一見こむずかしく思えますが、 Python らしいシンプルでわかりやすいインターフェイスになっているので意外とかんたんに使えます。

この他にも、ページ内のテキストを取得したり、マウスを操作したり、画面キャプチャを撮ったりと、通常ウェブブラウジングを行う上での基本操作が意外とシンプルなコードでできるようになっているので、興味がある方はぜひ公式ドキュメントをのぞいてみてください。

ちなみに、「ヘッドレスブラウザ」と呼ばれる PhantomJS などをインストールすればブラウザウィンドウを開かずに各種処理を行うことも可能となります。

もひとつちなみに、 Python バインディングではないおおもとの Selenium の方には、数多くのさまざまな「 Selenium ◯◯」が存在していて、 Selenium シリーズのようになっています。現在最も広く使われるものは次の2つになるでしょうか。

  • Selenium IDE
  • Selenium WebDriver


前者のIDEというのはFirefoxのプラグインとして動くもの、 WebDriverは今回ご紹介したPythonバインディングなどのようなコードによる操作を可能とするものです。


参考
Python Selenium ライブラリの公式ページ
- Selenium with Python — Selenium Python Bindings公式ドキュメント

同じくPyPIのページ
- selenium - Python Package Index

Seleniumのページ
- Selenium - Web Browser Automation

英語Wikipediaのページ
- Selenium (software) - Wikipedia

Seleniumの歴史も含めて解説されているページです。わかりやすいです。
- Selenium何とかっていうツールがやたら色々あるのはどういうわけなのか | 品質向上ブログ

2015/01/15

Python Tips:virtualenv で Python のバージョンを指定したい

Pythonの virtualenv で Python のインタプリタを指定する方法をご紹介します。

方法はかんたんで、 virtualenv コマンド実行時に python オプションでパスを指定するだけです。

$ virtualenv my_env --python=/usr/bin/python2.6

問題なく環境が生成できたら、「 ...done.」で終わるメッセージが表示されるかと思います。

環境ができあがれば通常どおり仮想環境に入ることができます。
$ cd my_env
$ source bin/activate  # Linux / OS X の場合
$ Scripts\activate  # Windows の場合
$ python -V
python 2.6.8
Pythonのバージョンを調べると指定したバージョンのものになっているはずです。

そして、環境から出ると、元のシステムのPythonに戻ることも確認できます。
$ deactivate
$ python -V
python 2.7.5

以上です。


ちなみに、 virtualenvwrapper にも同様のはたらきをする --python オプションが用意されています。
$ mkvirtualenv my_env --python=/usr/bin/python2.6

virtualenv コマンドにはこの他にも便利なオプションが豊富に用意されています。たとえばこんなもの。
  • --always-copy 仮想環境のPythonインタプリタをシンボリックリンクで用意するのではなくまるごとコピーして用意する
  • --system-site-packages システムのPythonライブラリに仮想環境からアクセスできるようにする
  • --no-pip デフォルトでインストールされる pip をインストールしないようにする
  • --prompt=MYPROMPT 仮想環境に入ったときにプロンプトの先頭に付加される文字を変更する

詳しくはvirtualenvコマンドのヘルプや公式ドキュメントをご覧ください。


参考
virtualenv — virtualenv公式ドキュメント

2015/01/08

サンプルコード:クイックソート

サンプルコード「クイックソート」をご紹介します。

クイックソートは、リストの中から要素をひとつ「ピボット」として選び、ピボット未満の要素とピボットよりも大きな要素とに残りの要素を分けていく再帰的アルゴリズムです。

Pythonのように内包表記を持った言語だととてもシンプル・エレガントに書けるのが特徴です。

def qsort(li):
    """クイックソートを行う

    @param li ソート可能な要素を持ったリスト
    @return li をソートした結果のリスト
    """

    # base case
    # 要素が空もしくは1つのリストはそのまま返す
    if len(li) < 2:
        return li

    # recursive case
    # 最初の要素をpivotとして、残りの要素をpivot未満と以上に分ける
    pivot = li[0]
    li_rest =  li[1:]
    smaller = [x for x in li_rest if x < pivot]
    larger = [x for x in li_rest if x >= pivot]

 # 分けたグループを再度 qsort に渡してから小さい順に結合する
    return  qsort(smaller) + [pivot] + qsort(larger)

リストを渡して使います。
qsort([])  # => []
qsort([1, 5, 3, 2])  # => [1, 2, 3, 5]
qsort(["tan", "pon", "am"])  # => ['am', 'pon', 'tan']


以上です。