Python tips

Last Update:2012/01/04
Python Version:だいたい2.7.X

体系だてて書くようなことじゃないちょっとしたメモ。

zipモジュールがShift-JISで文字化け

PythonのzipモジュールがShift-JISのダメ文字で文字化けしたり解凍が延々と続いたりする問題。

これはPythonのzipモジュールに限った話ではなくて、Macデフォルトの解凍アプリ(アーカイブユーティリティ)やOSのunzipコマンドでも似たような事象が起きる。

yattさんが解決策をブログに書いているので、そちらを参照。加えてそれに拡張したコードをgistに書いておられるので以下のリンクを参照。

yattさんのブログ

zipfile_extended_damemoji_for_py26.py

全角2文字、半角1文字のカウントする

Pythonはデフォルトの状態でもUnicodeにすれば日本語だろうが英語だろうが正しくカウントされる。 例えば

1
2
print(len(u"あいう"))
print(len(u"abc"))

これは同じ3文字になる。しかし今回はマルチバイト文字を半角2文字でカウントしたい。 というわけで RubyとPythonで全角文字を半角文字2文字として数える を参考に(ほぼ丸写しだけど)CGIから受け取った体で書いてみる。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
#coding: utf-8
import unicodedata

def count_zen(u_str):
    n = 0
    for c in u_str:
        wide_chars = u"WFA"
        eaw = unicodedata.east_asian_width(c)
        if(wide_chars.find(eaw) > -1):
            n +=1
    return n

u_input = "パイソンpython"

multi_len =count_zen(u_input.decode("utf-8"))
single_len = len(u_input.decode("utf-8")) - multi_len
u_length = multi_len * 2 + single_len

print("user input:%s\nmulti:%d\nsingle:%d\nall:%d"%(u_input,multi_len,single_len,u_length))

プロセッサ処理時間と実時間を測る

そもそもそも用途が違うかもしれないtime.clock()とtime.time()の話。

標準ライブラリのドキュメント:15.3. time — 時刻データへのアクセスと変換ython 2.7.2 documentation

time.time()はエポックタイム(1970年1月1日)から現時刻までの秒数を返す。 日付に関する機能など特に精度の求められない処理に関しては使っても問題なさそう。 精度がどの位なのかよくわからない(システムによるらしい)けど、0.01位までは信用してもいいのかな。

time.clock()はプロセッサ処理時間を秒数で返す。プロセッサが実際に動いた時間が返る上、精度も高い。 何かしら精度を求める場合はこっち。Pythonのベンチマークにも使われているようです。

普通はプロセッサが動く時間が短いほど体感時間も短くなるはずだけど、自分の作ったプログラムが改良によってどの位速くなったのか、程度の用途ならtime.timeでもいいのかなと思ったり。

time.sleep()を使うとtime.time()とtime.clock()の違いがわかりやすい。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import time

def t_time():
    sttime = time.time()
    time.sleep(1)
    #for i in range(50000):
    #   pass
    entime = time.time()
    return (entime - sttime)

def c_time():
    sttime = time.clock()
    time.sleep(1) #time.sleepの間はプロセッサは動かない
    #for i in range(50000):
    #   pass
    entime = time.clock()
    return (entime - sttime)

print("\ntime.time")
print(str(t_time()))

print("\ntime.clock")
print(str(c_time()))

これを実行すると次のようになる。

1
2
3
4
5
time.time
1.00103497505

time.clock
6.2e-05

time.timeはだいたい1秒、それに対してtime.clockはものすごく短い。プロセッサが動いていないことが解る。 それに対してfor文を5万回回すだけの処理(プログラミングのコメントアウト部分)を実行するとこんな感じになる。 もちろんtime.sleep()はコメントアウトしています。

1
2
3
4
5
time.time
0.00198411941528

time.clock
0.001927

だいたい同じ位の時間。

ファイルの権限変更や削除

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import os
#読み込み可能か? y:True n:False
os.access("tmp",os.R_OK)

#書き込み可能か? y:True n:False
os.access("tmp",os.W_OK)

#実行可能か? y:True n:False
os.access("tmp",os.X_OK)

#権限の変更
os.chmod("v.txt",0755)

#削除
os.remove("v.txt")

#ディレクトリを作成する
os.mkdir("test")

#カレントディレクトリのファイルとディレクトリ一覧を得る(lsコマンドと同じ)
os.listdir(".")

#osのコマンドを実行する(mkdirはos.mkdirで実行した方が良い)
os.system("mkdir hoge")

import commands

#osのコマンドを実行し、戻り値としてコマンドの結果を得る
print(commands.getoutput("ls"))

パス名とファイル名を分ける

1
2
3
path = "/usr/bin/python"
print(os.path.split(path))
#('usr/bin', 'python')

拡張子とファイル名を分ける

1
2
3
path = 'hoge/test.txt'
print(os.path.splitext)
#('hoge/test','.txt')

splitextは多分splitとextensionの略記。

ディレクトリ丸ごとコピー

1
2
import shutil
shutil.copytree("org/dir","path/to/dir")

shutilモジュール は高レベルのファイル操作を多数提供している。