Pythonのcmdモジュール

cmdを使えばコマンドラインのツールを簡単に作れる

コマンドループは

line = self.precmd(line)
stop = self.onecmd(line)
stop = self.postcmd(stop, line)

となっているのでpre,postのフックが効く。onecmdのほうはdo_をつけたメソッドを呼び出している。

cmd, arg, line = self.parseline(line)
if cmd == '':
    return self.default(line)
else:
    try:
        func = getattr(self, 'do_' + cmd)
    except AttributeError:
        return self.default(line)
    return func(arg)

getattrでメソッドを呼び出して、引数与えて実行した結果を返している。動的にメソッドの適用したい場合にはこうやればいいのか。

Pythonでファイル更新検知して任意のコマンドを実行する簡易コマンドを作った

Sphinx使っているのだけどファイルを更新するたびにmake htmlと打って確認するのがめんどくさい。linuxだったらpyinotifyがあるんだけど、macbookでは使えない。

簡易コマンド書いた。

#!/usr/bin/env python

import os
from time import sleep, strftime, localtime
import sys
import commands

filename = sys.argv[1]
mycommand = sys.argv[2]

def get_mtime():
    return os.stat(filename).st_mtime

mtime = get_mtime()
while 1:
    sleep(1)
    new_mtime = get_mtime()
    if mtime != new_mtime:
        mtime = new_mtime
        commands.getoutput(mycommand)
    print "done: %s ( %s )" % (mycommand, strftime("%a, %d %b %Y %H:%M:%S", localtime(mtime)))

監視対象のファイルを第一引数に、更新されたら実行するコマンドを第二引数に。

$ wdo docutils.rst "make html"
done: make html ( Wed, 06 Apr 2011 05:12:30 )
done: make html ( Wed, 06 Apr 2011 05:26:27 )
done: make html ( Wed, 06 Apr 2011 05:28:36 )
done: make html ( Wed, 06 Apr 2011 05:33:35 )
done: make html ( Wed, 06 Apr 2011 05:33:45 )

そうです、お分かりの通り早朝からdocutilsのソースを読んでいるのです。

ちなみにpyhttpd='python -m SimpleHTTPServer'っていうalias切っているので、makeで生成されたhtmlはlocalhost:8000で見てる

参考

rst.elモードを導入した

docutilsの中見てたら、emacs用のelがあったので入れてみた。

ヘッダの色が分かりづらかったのでM-x customize-faceで変更した。

rst.el

参考

KVM徹底入門が面白い

さくらのVPSで採用されているというKVMに興味を持ったので書籍を探してみたら、これがヒットしたので早速購入して読んでみた。

ProductName KVM徹底入門 Linuxカーネル仮想化基盤構築ガイド
平 初
翔泳社 / 3444円 ( 2010-07-08 )


ちなみにKVMとは

第1回 Linux標準の仮想化技術「KVM」の仕組み

KVMは、Linux Kernel自体をハイパーバイザとする仕組みで、正式名称を「Kernel-based Virtual Machine」といいます。KVMは現時点では、Intel VT-xやAMD-VといったCPUの仮想化支援機能を必要とし、完全仮想化によりOSの仮想化環境を提供します。

本書の内容は、仮想化全般の基礎知識から、インストール、導入まで。あとはコマンドのちょっとしたリファレンスが付いてくる感じ。Amazonのレビューにある通りひと通り試したことある人には物足りない内容かも知れないが、予備知識無しでKVMが知りたいのならば手軽に読めてよいと思う。

僕の場合にはこういう内容が知りたかったのだけど、ライブマイグレーションの話題しか触れてなかったのでそこはちょっと残念だったかな。

自分の職場はサーバー管理のスキルのない人間が管理者をヤラざるを得ず、ハードウェアを移行するたびに、(昔作ったサービスが移行できずに)サーバー環境が劣化していくという結構悲惨な状況だったりするわけだ。そもそもサーバー管理自体が本来の仕事と関係なくて片手間なのでしょうがなかったりするので、仮想化しとけばさくっと移行できて、ハードウェア移行の際のコスト減らせるかなぁという期待感からKVMに興味を持ったのだ。

特に7章でPythonとlibvirtを使ったプログラミングの例が出ているようにPythonを利用して色々できそうなので、サーバー管理の省力化に貢献しそうな気はするんだよなぁ。

  • 仮想マシンの導入には複数の方法がある
  • ホストから見た場合、VCPUはQEMUが立ち上げるスレッドに対応する。
  • 実CPUの数を超えてVCPUを割り当てることも可能だが、あまり意味はない
  • HugePageの利用シーンは?
  • virtio-balloonでメモリの確保と開放
  • live migration
  • ネットワークの設定の仕方は主に2つある
  • libvirtdでのプログラミング

pythonのsplit

splitの第二引数を与えると分割数を指定できる

>>> "test.tar.gz".rsplit('.')
['test', 'tar', 'gz']
>>> "test.tar.gz".rsplit('.',1)
['test.tar', 'gz']

perlだとこんな感じか(re.plで確認)

$ split /\./, "test.tar.gz"
$VAR1 = 'test';
$VAR2 = 'tar';
$VAR3 = 'gz';
$ split /\./, "test.tar.gz", 2
$VAR1 = 'test';
$VAR2 = 'tar.gz';

perlでrsplit相当のことやるにはどうすんだろか?

Amazon アフィリエイトのレポートをメールで自動で受けとる (Python)

Amazon アフィリエイトのレポートをメールで自動で受けとる 2011年版を見て、毎回アクセスして確認すんのは面倒なので僕もやっとこうと思った。

普段こういう作業ってperlでやってしまうことが多いのでPythonのmechanize使うのは初めてだ。あと、pyquery使うのも初めてだったりするが、jQuery知ってればサクっと使えてかなり便利。

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

# kzfm <kerolinq@gmail.com>

from mechanize import Browser
import smtplib
from email.MIMEText import MIMEText
from email.Header import Header
from email.Utils import formatdate
from pyquery import PyQuery as pq

email = 'XXXXXXXX@gmail.com'
password = 'XXXXXXXXXXXX'
amazon_url = 'https://affiliate.amazon.co.jp/'

def get_amazon_data():
    br = Browser()
    br.set_handle_robots(False)
    br.addheaders = [('User-agent', 'Mozilla/5.0 (X11; U; Linux i686; en-US; \
     rv:1.9.0.1) Gecko/2008071615 Fedora/3.0.1-1.fc9 Firefox/3.0.1')]

    br.open(amazon_url)

    br.select_form(name="sign_in")
    br["email"] = email
    br["password"] = password

    response = br.submit()

    d = pq(response.get_data())
    return [data.text for data in d('div').filter('.data')]

def send_mail(data):

    from_addr = email
    to_addr   = email
    subject   = u'Amazonアフィリエイト'
    body      = u"""
発送済み商品合計: %s
売上合計: %s
注文済み商品: %s
クリック数: %s
あなたのコンバージョン: %s
""" % tuple(data)

    msg = MIMEText(body.encode("utf-8"),'plain','utf-8')
    msg['Subject'] = Header(subject, 'utf-8')
    msg['From'] = from_addr
    msg['To'] = to_addr
    msg['Date'] = formatdate()

    s = smtplib.SMTP('smtp.gmail.com', 587)
    s.ehlo()
    s.starttls()
    s.ehlo()
    s.login(email, password)
    s.sendmail(from_addr, to_addr, msg.as_string())
    s.close()

if __name__ == '__main__':
    amazon_data = get_amazon_data();
    send_mail(amazon_data)

11.04.03

4/1からちょっとデザインが変わったようで、紹介料率の項目がなくなっていたので修正した。

SphinxをWikiのかわりに利用する

wikiやめたのでSphinxにメモるようにしてます。

で、ちょっと悩んでいるのがmake html後の手順だ。

現在/var/www/html以下はgitで管理していて、/var/www/html/[sphinx_html]みたいにドキュメントを置こうかなと考えているんだが、それってクライアント側でmake htmlして_build/htmlをcp -Rして/var/www/htmlを管理している方のGitに管理させるのがいいのかそれとも分けて管理してサーバー側で改めてmake htmlするようにしたほうがいいのかと。

あとはmake htmlしたあとの_buildディレクトリってもうちょっと自動的に公開されるようにできんかなと。

自動化といえば作業しているrstを監視しといてrstが更新されたら裏で自動的にmake htmlかかるようにできんかなとかも思った。

追記 11.04.02

Makefile読んだらmake htmlは

html:
        $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
        @echo
        @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."

ということなのでSPHINXBUILDつまりsphinx-buildコマンドを直接呼び出して明示的にBUILDDIRを指定してやればいいってことだった。

modulefinderでimportされているモジュールを列挙する

引数にファイルを指定して呼び出せばそのファイルでimportされているモジュールを列挙してくれる

import cPickle

with open("list.txt","w") as f:
    cPickle.dump([1,2,3,4,5],f)

with open("list.txt","r") as f:
    a = cPickle.load(f)

print a

こんなのだと

  Name                      File
  ----                      ----
m __main__                  pickletest.py
m cPickle                   /opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/lib-dynload/cPickle.so

こんな感じ。

reをコンパイルしとくと速いってのは割と単純な理由だった

ソース見ると毎度毎度コンパイルしてた

def match(pattern, string, flags=0):
    """Try to apply the pattern at the start of the string, returning
    a match object, or None if no match was found."""
    return _compile(pattern, flags).match(string)

def search(pattern, string, flags=0):
    """Scan through string looking for a match to the pattern, returning
    a match object, or None if no match was found."""
    return _compile(pattern, flags).search(string)

あとはこれで使ったexperimentalなScannerクラスのコード読んだ。

class Scanner:
    def __init__(self, lexicon, flags=0):
        from sre_constants import BRANCH, SUBPATTERN
        self.lexicon = lexicon
        # combine phrases into a compound pattern
        p = []
        s = sre_parse.Pattern()
        s.flags = flags
        for phrase, action in lexicon:
            p.append(sre_parse.SubPattern(s, [
                (SUBPATTERN, (len(p)+1, sre_parse.parse(phrase, flags))),
                ]))
        s.groups = len(p)+1
        p = sre_parse.SubPattern(s, [(BRANCH, (None, p))])
        self.scanner = sre_compile.compile(p)
    def scan(self, string):
        result = []
        append = result.append
        match = self.scanner.scanner(string).match
        i = 0
        while 1:
            m = match()
            if not m:
                break
            j = m.end()
            if i == j:
                break
            action = self.lexicon[m.lastindex-1][1]
            if hasattr(action, '__call__'):
                self.match = m
                action = action(self, m.group())
            if action is not None:
                append(action)
            i = j
        return result, string[i:]

未読のPython標準モジュール

最近朝早く起きて読みまくっているので、結構減った

標準モジュール読むと、コードのお作法とか勉強になるし、あーこうなってんのか!という気付きが何度もあって階段登ってるという実感があって楽しい。

ProductName 初めてのPython 第3版
Mark Lutz
オライリージャパン / 4830円 ( 2009-02-26 )


  • bdb.py
  • cProfile.py
  • code.py
  • difflib.py
  • doctest.py
  • gettext.py
  • htmllib.py
  • httplib.py
  • modulefinder.py
  • optparse.py
  • pdb.py
  • pipes.py
  • profile.py
  • pstats.py
  • pydoc.py
  • random.py
  • re.py
  • repr.py
  • shutil.py
  • socket.py
  • subprocess.py
  • threading.py
  • token.py
  • tokenize.py
  • unittest.py
  • urllib.py
  • urllib2.py
  • xmllib.py
  • xmlrpclib.py

cPythonのソースコードも読むと楽しいのかな?