osモジュールについて
最近、ファイルの移動(リネーム)や移動後の確認などをpythonでやることが多く、そのためosモジュールにはお世話になりっぱなし。せっかくなんでちょっとメモを書いてみます。
- 環境はwindows NT系(ぶっちゃけXP)
- sitecustomize.py
- setdefaultencoding("utf8")は敢えて無し(エンコードはasciiのまま)
- osモジュール
- 文字列リテラル
os.listdir(path)
osモジュールでの処理は、必ずunicodeになるようにした上で処理を行う。さもなくばファイル名が誤認識されたり、renameの場合では最悪ファイルが消えたりするかも(重複ファイル名で上書きされて消えたり)。
下記の例では、pathをハードコーディングしています。codingをcp932に指定したうえでu"ほげほげ"のリテラルを使っています。さらにwindowsの場合pathの区切り文字がバックスラッシュ"\"なので、r"ほげほげ"を指定してraw文字列リテラルとしてやります*1。結果、ur"ほげほげ"としました。
# coding: cp932 import os print u"urで文字指定" , "*"*20 path=ur".\日本語のフォルダ\新しすぎるフォルダ" for each in os.listdir(path): print each.encode("cp932"), type(each)
print文のencode("cp932")は、cmd.exeで標準出力にだす場合には不要かもしれませんが、リダイレクトでファイルに吐こうとするとUnicodeDecodeErrorを出すので書いたほうがいいです。
実行すると下記のように出ます。
urで文字指定 ********************
やや意味のあるファイル.txt
意味のないファイル.txt
unicodeでpath処理したから、見つかったファイル名もunicode扱い、ってことですかね。
ちなみに入力pathをunicode型にしないでos.listdir()にかけると
# coding: cp932 import os print "rで文字指定" , "*"*20 path2=r".\日本語のフォルダ\新しすぎるフォルダ" for each in os.listdir(path2): print each, type(each)
上のようなコードになりますが、結果は
rで文字指定 ********************
やや意味のあるファイル.txt
意味のないファイル.txt
str型になりました。
型を間違えたまま処理を続けるとpathの文字列がおかしくなった状態で処理されてしまう可能性があるので、いつもと同じく入力時にdecode、出力時にencodeを心がけたほうが無難かと。
os.path.join(path1, path2, ...)とos.walk(path)
os.walk()とos.path.join()の組み合わせは王道じゃないでしょうか。
os.walk()は、詳細は知りませんが、要するにディレクトリを再帰的に移動してあるディレクトリへの相対パス(root)、含まれるディレクトリのリスト(dirs)、含まれるファイルのリスト(files)を返します。つまり現在のワークディレクトリからはroot + "\" + dirsでアクセスできます。ただしこのように\で繋ぐとwindows環境依存となるため、パスを繋げる目的でos.path.join()を使うべきです。
#coding: cp932 import os path=ur".\日本語のフォルダ" for root,dirs,files in os.walk(path): print type(root), root for eachfile in files: print u"\t└ ", type(eachfile), eachfile , fullpath = os.path.join(root,eachfile) print os.access(fullpath,os.F_OK)
os.access(path, os.F_OK)はpathの有無を調べてTrueあるいはFalseを返します。参考まで。
os.renames(src,dst)
こいつがまだよく分かっていない。
src,dstの型はunicodeで大丈夫なのか、あるいは環境に合わせる(今回はcp932)なのか。
そのうち調べる、、、