XREAで好きなバージョンのPythonを使う方法2

やんごとなき事情によりxrea内でWEBサーバを移動しました。

というわけで、このブログ(web.pyによる自作ブログ)を移したわけですが、今までのようにバイナリ化して動かすにはサーバと似た環境が手元にないといけません。が、移動した先のサーバでは環境がだめ。

ということで、python2.5をxreaにインストールしました。virtual-pythonもいいんですが、xreaのサーバはpython2.4なので。ちょっと工夫すれば入るし、快適ですね。以下作業ログ。

Pythonをインストール

まずはPythonのソースをダウンロードしてコンパイル。~/root/usr/localにいれます。

 code
  1. mkdir -p ~/root/usr/local/src
  2. cd ~/root/usr/local/src
  3. wget http://www.python.org/ftp/python/2.5.4/Python-2.5.4.tgz
  4. tar zxvf Python-2.5.4.tgz
  5. cd Python-2.5.4
  6. ./configure --prefix=~/root/usr/local
  7. make
  8. make install
  9.  

サクっと入ります。で、次にeasy_installを入れるわけですが、はいりません。OpenSSLとの絡みでhashlib.md5が使えないから。easy_installを入れるときにmd5を検証するのに使ってるんですよね。

hashlibをインストール

なんで、自前でhashlibを単体でいれます。

 code
  1. cd ~/root/usr/local/src
  2. wget http://code.krypto.org/python/hashlib/hashlib-20081119.tar.gz
  3. tar zxvf hashlib-20081119.tar.gz
  4. cd hashlib-20081119
  5. vi setup.py
  6.  

はい、setup.pyを編集しましょう。普通にbuildするとこれでもmd5が入りません。

 code
  1. 105   if (ssl_inc_dir and
  2. 106     ssl_lib is not None and
  3. 107     openssl_ver >= 0x00907000):
  4. 108
  5. 109     print 'Using OpenSSL version 0x%08x from' % openssl_ver
  6. 110     print ' Headers:\t', ssl_inc_dir
  7. 111     print ' Library:\t', ssl_lib
  8. 112
  9. 113     # The _hashlib module wraps optimized implementations
  10. 114     # of hash functions from the OpenSSL library.
  11. 115     exts.append( Extension('_hashlib', ['_hashopenssl.c'],
  12. 116                include_dirs = [ ssl_inc_dir ],
  13. 117                library_dirs = [ os.path.dirname(ssl_lib) ],
  14. 118                libraries = osNameLibsMap[os.name]) )
  15. 119   exts.append( Extension('_sha', ['shamodule.c']) )         
  16. 120   exts.append( Extension('_md5',                  
  17. 121           sources = ['md5module.c', 'md5.c'],
  18. 122           depends = ['md5.h']) )
  19.  

119-120あたり、強制的に_md5を入れるようにします。あとは

 code
  1. ~/root/usr/local/bin/python setup.py build
  2. ~/root/usr/local/bin/python setup.py install
  3.  

hashlibが入ります。

easy_installをインストール

これでmd5が使えるようになったので

 code
  1. cd ~/root/usr/local/src
  2. wget http://peak.telecommunity.com/dist/ez_setup.py
  3. ~/root/usr/local/bin/python ez_setup.py
  4.  

これで無事easy_installが入ります。あとは

 code
  1. ~/root/usr/local/bin/easy_install -U -Z MySQL_Python
  2.  

てな感じで必要なモジュールを入れていきましょう。

というわけで

わりと普通にxreaでPythonが使えています。

01.06.10/12am

2008年振り返り

2008年も終わり、今日で仕事納めということでよくあるまとめな感じです。

生活的に

就職して2年目ですね。働き方とか環境にも幾分慣れて、メリハリをつけてそれなりに充実した生活を送れたと思います。

食生活だけが若干気がかりですが(学生時代から1日1食です)、社内健康診断も全項目かなり良好な数値だったので、まだこのままいこうと思います。ちなみに、肥満率は-25%という素晴らしい数値でした。体重50kgくらいはほしいなあ、とは思っていますが、ここが壁ですね。

睡眠時間も平均して短く保てたと思います。たぶん、4時間睡眠くらい。個人的にはやはり徹底した小食が貢献している気がします。

そして、今年も風邪をひきませんでした。周りから不健康そうに見られるのですが、このようにいたって健康なのでした。というか、俺が不健康なのは整形外科的なところだけなのです。整形外科的には3箇所ほど手術したほうがいいところがあります(笑

技術的に

  • PythonでRakeもどき
  • Pythonのニコ動ライブラリ
  • ScalaでなんちゃってFactor処理系
  • Python版Yahooテキスト解析APIライブラリ
  • Blogソフトウェアを自作に移行
  • PythonのS式パーサ、ダンパライブラリ
  • Pythonのパターンマッチライブラリ

このブログで出したのはこんなもんですかね。これだけみると年の前半は引き続きScalaをさわりつつ、やっぱりPythonという感じですね。

そして、大きな変化はブログを独自実装に切り替えたことでしょう。ようやくWordpressのバージョンアップ地獄から逃れました。あ、この記事を書くついでに、web.pyのバージョンを0.31にあげました。いろいろ変わってたのでそこそこ対応は大変だったんですが、まぁなんとか。例によってテストはあまりしてないのでおかしいとこはあるかも。

数ヶ月、独自ブログソフトで運用しましたが、非常に快適です。出力されるXHTMLは当然段違いにキレイだし(HTML-lintで96-99点くらいです)、負荷も問題ないっぽいです。一応、xrea使っている人のために参考までに書いておくと、web.pyをcgiで動かして、負荷はスパムアタックを受けたときで30pt程度、通常はずっと0ptでした。おそらく、よっぽど酷いコードを動かさない限り、web.pyであればxreaでもcgiで運用して問題なさそうです。

今年の言語・・・というほどさわった新しい言語はないかもしれないです。ただ、趣味ではC言語を書くことが断然増えましたね。そのうちC言語で処理系を実装する系の、このテのブログでは定番の記事を書こうかと思っています。

今年触っていた言語は量ではPython > C言語 > Scheme > Scalaとなると思います。ここから見て、やはりシンプルなものが好きなんでしょう、俺は。PythonはRubyに比べて圧倒的にシンプルです。C言語はまぁ書き方(ポインタとか配列とか)ややこしいじゃんか、といわれるかもしれませんが、基本はシンプルです。Schemeはどうみてもシンプルです、ありがとうございました。

技術的な勉強面では基礎的な部分をちょこちょこ勉強してました。アルゴリズム方面、言語処理系関連技術(パーサ、GC、VMなどなど)はちょこっと前進した気がします。

おそらく、来年もPython、C言語を中心に触っていくと思います。このブログは技術系ネタがメインなので、月イチくらいのペースでは書いていこうと思っています。ま、実はJavascriptも触ってるんですが、あまり書くことはありません。

その他の趣味とか

実は今年はわりと、プログラミングとか仕事以外の趣味を頑張っていたような気もします。まぁ音楽系なんですが。

中学まで10年くらい、ピアノとエレクトーンを習っていました。が、全く上達しませんでした。どうしてもピアノという楽器、音色に特別な魅力を感じることが出来なかったし、弾く事に気持ちよさを見出せなかった。そして、中学くらいでAtari Teenage Riotにハマり、以後デジタルハードコア、ガバ、スピコアなんかに浸かっていきました。ピアノで弾くような曲とは違う、自分にとって一番心にひびく音楽でした。そこから打ち込み一辺倒、中古でSC-88(Proはわずかに手がとどかなかった。。。)を買って、自作曲を作ったり割と能動的に音楽を楽しんでいました。

そして大学ではバイトでプログラミング三昧。家にいる時間がほとんどない、ということで作曲とかからは完全に遠ざかったのです。が、やはりどこかでもう少し能動的に音楽を楽しみたいなあ、という思いはもっていたので、就職を期にエレキギターをちょくちょく触ることにしました。そもそもギターは学生時代、作曲していたときにコードを確認する程度にしか使っていなかったので、ほとんど弾けたもんじゃなかったんですが、今はまぁ、それよりはマシです(笑

なにより、ピアノと違って、やっぱ歪んだギターの音は好きです。弾くのもピアノに比べて気持ちよさが違う。気持ちよさを感じることができるので、継続的に練習できてます。

というわけで

そこそこいい年でした。来年もマイペースに頑張っていきたいところ。

12.29.08/10pm

Python: パターンマッチしてみる

なんか、趣味では最近はC言語ばっかりだったりするわけですが。

さて、関数型言語系をカジった人なら誰しも取り付かれる、モノ、それがパターンマッチ。パターンマッチが使えると、とにかく直感的にコードをかけますよね。

つーわけで、Pythonでパターンマッチを実装してみました。機能的には

  • リスト,タプルに対するパターンマッチ
  • パターン変数への束縛
  • ガード条件
  • 任意のオブジェクトに対するパターンマッチ
  • 部分パターンの束縛(Ocamlのas)

あたりを実装してみました。これだけあれば、かなり便利にコードをかけます。できるだけ、手軽に書けるように工夫してみました。こんな感じです。

変数束縛とガード。getattrでごにょごにょしてるので簡単にかけます。

python code
  1. m = Match([1,2,3])
  2. if m.when([1,2,m.var]) and m.var > 2:
  3.   print m.var
  4. # >> 3
  5.  

こう使えば、Pythonに念願のswitchが!

python code
  1. m = Match(10)
  2. if m(9):
  3.   print 1
  4. elif m(10):
  5.   print 2
  6. else:
  7.   False
  8. # >> 2
  9.  

部分パターンを束縛してみます。[1,2,m.var]全体をallというパターン変数に束縛します。

python code
  1. m = Match([1,2,3])
  2. if m.when([1,2,m.var]) and m.var > 5:
  3.   False
  4. elif m.when(m._as_all([1,2,m.var])):
  5.   print m.all
  6.   print m.var
  7. else:
  8.   raise StandardError("")
  9. # >> [1, 2, 3]
  10. # >> 3
  11.  

任意のオブジェクトにも使えます。いわゆるレコードに対するマッチも簡単にできるということです。

python code
  1. class Test(object):
  2.   def __init__(self, v1, v2):
  3.     self.v1 = v1
  4.     self.v2 = v2
  5.   def __repr__(self):
  6.     return "Test(%s, %s)"%(repr(self.v1), repr(self.v2))
  7. m = Match([1, Test(2, 3)])
  8. if m.when([1, m._class(Test, {"v1":2, "v2": m.v2})]):
  9.   print m.v2
  10. else:
  11.   False
  12. # >> 3
  13.  

オブジェクトに対するパターンマッチは__match__メソッドを定義するとカスタマイズできます。ここらのアイデアはScalaからいただきました。

python code
  1. class Test2(Test):
  2.   def __match__(self):
  3.     return {"value": self.v1 + self.v2}
  4. m = Match([1, 2, Test2(3,4)])
  5. if m.when([1,2, m._class(Test2, {"value": m.var})]):
  6.   m.var
  7. else:
  8.   False
  9. # >> 7
  10.  

結構いい感じな気がします。

ダウンロード

patternmatch.py

実装のお話

ソースコードはこんな感じ。

python code
  1. class Match(object):
  2.   class _var(str): pass
  3.   class _class(object):
  4.     def __init__(self, klass, attrs):
  5.       self.klass= klass
  6.       self.attrs= sorted(attrs.iteritems())
  7.     def match(self, m, obj):
  8.       props = getattr(obj, "__match__", lambda: obj.__dict__)()
  9.       return issubclass(obj.__class__, self.klass) and \
  10.             m.when(self.attrs, sorted(props.iteritems()))
  11.   class _as(object):
  12.     def __init__(self, name, pattern = None):
  13.       self.name = name
  14.       self.pattern = pattern
  15.     def __call__(self, pattern):
  16.       self.pattern = pattern
  17.       return self
  18.  
  19.   def __init__(self, obj):
  20.     self.obj = obj
  21.     self.bind = {}
  22.  
  23.   def __getitem__(self, key):
  24.     if not self.bind.has_key(key):
  25.       if key.startswith("_as_"):
  26.         return self._as(self._var(key[4:]))
  27.       return self._var(key)
  28.     return self.bind[key]
  29.   __getattr__ = __getitem__
  30.   __call__ = lambda self, *a, **k : self.when(*a, **k)
  31.  
  32.   def when(self, pattern, obj = None):
  33.     if not obj: obj = self.obj
  34.     if isinstance(pattern, (self._var, self._class, self._as)):
  35.       if isinstance(obj, (list, tuple)):
  36.         pattern = [pattern]
  37.         obj = [obj]
  38.  
  39.     if not isinstance(obj, (list, tuple)) and \
  40.       not isinstance(pattern, (list, tuple)) :
  41.       obj = [obj]
  42.       pattern = [pattern]
  43.  
  44.     if not isinstance(obj, (list, tuple)) or \
  45.       not isinstance(pattern, (list, tuple)) :
  46.       self.bind = {}
  47.       return False
  48.  
  49.     if len(obj) != len(pattern):
  50.       if not ((pattern[-1].__class__ == self._var) and pattern[-1].startswith("__")):
  51.         self.bind = {}
  52.         return False
  53.  
  54.     for i, (value, pat) in enumerate(zip(obj, pattern)):
  55.       if value == pat:
  56.         continue
  57.       elif pat.__class__ == self._var and pat.startswith("__"):
  58.         self.bind[str(pat)] = obj[i:]
  59.         return True
  60.       elif pat.__class__ == self._var:
  61.         self.bind[str(pat)] = value
  62.       elif pat.__class__ == self._class:
  63.         if not pat.match(self, value):
  64.           self.bind ={}
  65.           return False
  66.       elif pat.__class__ == self._as:
  67.         if not self.when(pat.pattern, value):
  68.           self.bind ={}
  69.           return False
  70.         self.bind[str(pat.name)] = value
  71.       elif isinstance(value, (list, tuple)) and isinstance(pat, (list,tuple)):
  72.         if not self.when(pat, value):
  73.           self.bind = {}
  74.           return False
  75.       else:
  76.         self.bind = {}
  77.         return False
  78.  
  79.     return True
  80.  

まぁわりかしシンプルですね。


今年も終わりが近づいてまいりました。年をとると時間がすぎるのが速いナァ・・・と痛感しております。

12.11.08/01am

About

Author:yuin(http://inforno.net/)

文学部文化学科卒という生粋の文系趣味プログラマ。

主にRuby、Javascript、PHP、JAVA,Python,C,Scala,Schemeなどを使っています。今はPythonな感じかもしれない。今後作曲活動なども復活するかもしれない。

Pages