Home > Python Archive

Python Archive

[Python][lxml]依存ライブラリ?が足りなくてインストールではまる

Fedora6に入れようと思ったんだけど、コンパイルエラーが出る。
なんだかヘッダーファイルが足りなそうな感じのエラー。

libxml2とlibxsltだけじゃなくって、それぞれ*-develが必要なのか。

以下の情報に感謝。

lxmlがインストールできない

[Python]2分探索

ビューティフルコードの7章で、この章を読み進む前に2分探索を実装しろと書いてあった。
ということでPythonで実装してみる。

最初に書いたコードはこれ。

PYTHON:
  1. def mybinarysearch(a, t, f):
  2.     n = len(a)
  3.     if n <= 0:
  4.         return -1
  5.     if n == 1:
  6.         if a[0] == t:
  7.             return 0
  8.         else:
  9.             return -1
  10.     m = int(n / 2)
  11.     r = f(t, a[m - 1])
  12.     if r <= 0:
  13.         x = mybinarysearch(a[:m], t, f)
  14.         if x>= 0:
  15.             return x
  16.         else:
  17.             return -1
  18.     else:
  19.         x = mybinarysearch(a[m:], t, f)
  20.         if x>= 0:
  21.             return m + x
  22.         else:
  23.             return -1

配列、検索対象、比較関数を渡す。
さすがにこれだと、いちいちlenを計算していたり効率悪すぎだし、コードも汚いのでもう少しましにする。

PYTHON:
  1. def mybinarysearch(a, t, f):
  2.     def func(array, i, n):
  3.         if n <= 0:
  4.             return -1
  5.         elif n == 1:
  6.             if f(array[0], t) == 0:
  7.                 return i
  8.             else:
  9.                 return -1
  10.         else:
  11.             m = int(n / 2)
  12.             if f(t, array[m - 1]) <= 0:
  13.                 return func(array[:m], i, m)
  14.             else:
  15.                 return func(array[m:], i + m, n - m)
  16.     return func(a, 0, len(a))

これで、配列中で対象に合致する最小のIndexが返るはず?

最小にこだわらなければこうなるかな

PYTHON:
  1. def mybinarysearch(a, t, f):
  2.     def func(array, i, n):
  3.         if n <= 0:
  4.             return -1
  5.         m = int(n / 2)
  6.         r = f(t, array[m])
  7.         if r == 0:
  8.             return i + m
  9.         elif r <0:
  10.             return func(array[:m], i, m)
  11.         else:
  12.             return func(array[m + 1:], i + m + 1, n - m - 1)
  13.     return func(a, 0, len(a))

この章の主題であるテストはまだちゃんとやってない。

これから考えてやってみよう。
再帰で書いてしまったので遅そうだけど、2分探索だったらあふれることはないだろう。

さくらでPython外部モジュールを使うときの注意点メモ

先週さくらインターネットの共用サーバーで、OSのバージョンアップがあった。
なぜかDjangoで動いているサービスが動かなくなったので対処した。

どうやら、環境変数を1行目で渡しているのが動かなくなってしまったっぽい。
これがだめ。

#!/usr/bin/env PYTHONPATH=/home/XXX/local/lib/python:/home/XXX/local/lib/python/site-packages python

ということでsys.path.appendでローカルの外部モジュールをおいてあるディレクトリを追加したんだけど、今度はMySQLdbをimportできなくなった。
OSのバージョンアップにあわせてMySQLdbも入れなおしたんだけど、やっぱりimportできない。

sh1.2 pyblosxom : さくらでPythonモジュール設定: 訂正版

sys.path.append()ではなく、site.addsitedir()を使わないとsite-packages以下にeasy_installを使ってインストールしたモジュールパスが反映されない。

ということでした。

最近本業が忙しいのに加えて土日は空手関係の行事(稽古とか審判とか審判とか)でつぶれまくっているので、全くブログ更新できていませんが、ちゃんと生きています。

MySQL-pythonのインストール失敗

自宅のLinux(Fedora Core6)サーバーにsvn版のDjangoをいれたら、MySQLdb(MySQL-python)が古いというエラーが出た。
という訳でアップデートしようとしたら、なぜかコンパイルが通らない。
ヘッダーファイルが無いとか言っている。

ちょっと(※)悩んだけど、よくよく見るとmysql-develが入っていなかった。

※ほんとはちょっとじゃなくてかなり悩んだ。

python forループの備忘録(複数配列、インデックス値)

知ってれば当たり前だけど、知らないといけてないコードを書き続けそうなので備忘録。

複数の要素数が同じ配列をforループで同時に扱いたいときはzipを使う

for (x, y) in zip(range(1, 11), range(11, 21)):
print x
print y

forループの中でインデックス値を利用したい場合は、enumerate。

for (i, x) in enumerate(range(11, 21)):
print i
print x

合わせ技も可能。

for i, (x, y) in enumerate(zip(range(1, 11), range(11, 21))):
print i
print x
print y

多言語でインデックス値ループに慣れてると
for i in range(len(array_a)):
とかしちゃう。

Pythonのリスト内包表記でreduceは実現できる?

mapやfilterはそのままだからすぐに内包表記でOK。
本当ならreduceもループじゃなくってリスト内包表記で書けたらいいのに。

>>> a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> b = 0
>>> def funcA(x):
... global b
... b += x
... return b
...
>>> [funcA(x) for x in a]
[1, 3, 6, 10, 15, 21, 28, 36, 45, 55]
>>> b
55
>>>

うーん。
globalよりはClassのほうがまし?

>>> a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> class ClassA:
... b = 0
... def funcA(self, x):
... self.b += x
... return self.b
...
>>> c = ClassA()
>>> [c.funcA(x) for x in a]
[1, 3, 6, 10, 15, 21, 28, 36, 45, 55]
>>> c.b
55
>>>

うーん。。。。。。
普通にループにするか、複雑な処理だったらリストを処理する関数(中身はループだけど)を書いたほうがましかな。

※ 2007/5/19 5:00ちょっと前 追記
今、夢の中で誰かが破壊的代入がダメなんだよと言ってたので、ちょっと考えてみた。

普通にreduceだったらこう。
>>> a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> def funcA(x, y):
... return x + y
...
>>> reduce(funcA, a, 0)
55
>>>

で、さっきはreduceっぽい処理をグローバル変数への破壊的代入でなんとかしようとしてみた。
じゃー、破壊的代入をしないとこんな感じ?
>>> def funcB(func, xs, init):
... if len(xs)==0:
... return init
... elif len(xs)==1:
... return func(xs[0], init)
... else:
... return func(xs[0], funcB(func, xs[1:], init))
...
>>> funcB(funcA, a, 0)
55
>>>

これをどうにかして無理やり内包表記でやろうとすると、、、
無さそうですね、少なくとも私にはわかりません。。。

やっぱり夢は夢だったということで。
さっきは酔っ払ってて、今は寝ぼけてて、あんまり筋の良くない話になってるのかな。

無理矢理でもいいので、だれかreduceの代替案を知ってたら教えてください。

※追記 2007/05/21
reduceが廃止されたらやだなーと思って酔っ払って勢いで書いてしまった記事です

Pythonのリスト内包表記は楽しい

ちょっとした配列処理を簡単に書ける楽しさはかなりいい。
内包表記を多用した後でPHPとか書き始めると、"foreach" と書く前に、"new_array=[x * 2 ・・・" とか書きそうになってくそーと思うくらい。

PHP使ってると高階関数も恋しくなるときがある。
それから無駄にClassとか使わないで、functionの中にちょこっとfunctionって書きたくもなる。

やっぱり関数型言語をちゃんとやってみたほうがいいかも。

「ふつうのHaskellプログラミング」は読んで面白いと思ったけどまだ触ってない。
Lisp(←関数型っていっていいのか?)もちょこっと触っただけ。
流行のErlangでもやってみようかな。並列処理って言うのも面白そう。

Pythonを始めた理由

Pythonを始めた理由。
それはソースをみてきれいな感じがしたから。
この一言に尽きる。

比較にあがったのはPerlとRubyだけど、直感でPythonやってみようと思った。
Perlはあの記号モリモリな感じがどうにも好かなかった。ソースが読みにくくなりやすいという「噂」も気になった。
自分で書いてみてもなんかしっくりこないし。

RubyはPerlより好みっぽかったが、Pythonより記号が多そうな雰囲気とendがジャマに見えた。
ちょっと使ってみた感想だと、Pythonの方がシンプルな感じがしたのもRubyよりもPythonを選んだ理由。

あとはGoogleがPython使っているらしいというミーハー根性もかなり重要なファクターだったと思う。

みんなはどういう基準で言語を使い始めるのかなぁ?

SIerとかはマジメな比較とか評価とか好きそう。項目を立ててポイントつけちゃったりして。
そして、なぜか結局Javaが点数高くなっちゃうとか。

Pythonで簡易Apacheログ集計

仕事でWebサイトの負荷テストをやっている時に、PVをその場で簡単に調べたい場面があった。
車輪の再発明と思ったが、勉強によい機会だと思いPythonでスクリプトを書いてみた。

使い方は、
python logcheck.py file [interval]

fileはログファイルを指定。(標準入力の時は「-」)

intervalはログ集計の間隔を秒数で指定する。
1秒ごとにPV集計したければ1、1分ごとに集計したければ60と入力すればOK。
これを作ったときに、1秒ごと、10秒ごと、1分ごとなどいくつかに分けてグラフを見たかったので。
デフォルトは60秒です。

特定のURLへのアクセスをみるときは、ログファイルをgrepしてパイプでつなげてこのスクリプトを呼んでください。

勉強だと思って無駄にジェネレータとかクロージャとか使っていて、分かりにくいソースになっているかもしれないけど、もし気付いたところとかあれば添削してもらえると嬉しいです。

logcheck.py

PYTHON:
  1. #!/usr/bin/env python
  2.  
  3. import sys
  4. import time
  5.  
  6. def logcheck(f, interval):
  7.     log_time = 0
  8.     access_count = 0
  9.  
  10.     # functions for log interval
  11.     def calctime(log_time_str):
  12.         log_time = int(time.mktime(
  13.                     time.strptime(log_time_str.split()[3][1:],
  14.                         '%d/%b/%Y:%H:%M:%S')))
  15.         return log_time - (log_time % interval)
  16.  
  17.     def makerange(start, end):
  18.         return range(start + interval, end, interval)
  19.  
  20.     def isnotnext(a, b):
  21.         return b <a + interval
  22.  
  23.     gen = getonerow(f, calctime)
  24.  
  25.     while True:
  26.         try:
  27.             x = gen.next()
  28.         except (ValueError, IndexError):
  29.             continue
  30.         except StopIteration:
  31.             printcount(log_time, access_count)
  32.             break
  33.  
  34.         if isnotnext(log_time, x):
  35.             access_count += 1
  36.             continue
  37.  
  38.         if log_time:
  39.             printcount(log_time, access_count)
  40.  
  41.             for i in makerange(log_time, x):
  42.                 printcount(i, 0)
  43.  
  44.         log_time = x
  45.         access_count = 1
  46.  
  47.  
  48. def printcount(log_time, access_count):
  49.     if log_time:
  50.         print "%s %i" % (time.strftime('%d/%b/%Y:%H:%M:%S',
  51.                             time.localtime(log_time)),
  52.                         access_count)
  53.  
  54.  
  55. def getonerow(f, func):
  56.     for l in f:
  57.         yield func(l)
  58.  
  59.  
  60. def main():
  61.     try:
  62.         if len(sys.argv) <2:
  63.             print 'arg error'
  64.             return
  65.  
  66.         if sys.argv[1] == '-':
  67.             f = sys.stdin
  68.         else:
  69.             try:
  70.                 f = open(sys.argv[1], "r")
  71.             except:
  72.                 print 'can\'t open file'
  73.                 return
  74.  
  75.         if len(sys.argv)>= 3 and int(sys.argv[2]):
  76.             interval = int(sys.argv[2])
  77.         else:
  78.             interval = 60
  79.              
  80.         logcheck(f, interval)
  81.     except KeyboardInterrupt:
  82.         print "stoped by user"
  83.  
  84.     f.close()
  85.  
  86. if __name__ == '__main__':
  87.     main()

Home > Python Archive

Search
Feeds
Meta

Return to page top