2012年1月31日火曜日

shutil.move のバージョン依存性

Python で標準的に用いることが出来るモジュールの中に shutil というのがあります。これは shell utility のことで、move や copy のようにファイルのコピーやディレクトリに関する処理を行なうシェルコマンドに対応するメソッドが含まれています(なお、mkdir とかは os モジュールに入っている)。

先ほど気づいたのですが、shutil.move の挙動は python のバージョンによって異なるのでメモしておきます。チェックした環境は CentOS 5.6, bash です。以下のスクリプト movetest.py を試してみましょう。

# -*- coding: utf-8 -*-
from os import mkdir
from shutil import move

mkdir("src")
mkdir("dst")
f = open("spam", "w")
f.write("test")
f.close()
move("spam", "dst") # まず、テキストファイル "spam" を dst/ に移す
move("src", "dst") # 次に src/ を dst/ に移す

その結果、バージョン 2.6/2.7 と 3.x では直感的な振る舞いをするのですが、2.4 はちょっと違っています:
  • 2.4:
    Traceback (most recent call last):
      File "movetest.py", line 10, in ?
        move("src","dst")
      File "/usr/lib64/python2.4/shutil.py", line 190, in move
        copytree(src, dst, symlinks=True)
      File "/usr/lib64/python2.4/shutil.py", line 111, in copytree
        os.mkdir(dst)
    OSError: [Errno 17] File exists: 'dst' 
  • 2.6 / 2.7, 3.x:
    dst/ 以下に src/ と spam が存在する。
2.4 では、移動先のフォルダに中身が入っていると move 出来ないようです。そこで、spam ファイルを dst に移さないで空の状態の dst に対して src を move しようとすると次のようになります。
  • 2.4:
    src/ が dst/ にリネームされ、dst/ ディレクトリだけが残る。
  • 2.6 / 2.7, 3.x:
    dst/ 以下に src/ が存在する。
2.4 では普通のファイルをリネームするかのようなはたらきをします。

これで分かったように、普通のシェルコマンドと同じ挙動を期待するなら少なくとも 2.6 以降を利用するべきだということでしょう。 2.5 については確認してないので分かりませんが……。

ちょっと時代遅れな記事だったかもしれないですね。

*追記:
Python 2.5 は 2.4 と同じ振る舞いをするようです(MacOS 10.6 で確認)。2.5 --> 2.6 のタイミングで何かあったんでしたっけ。

0 件のコメント:

コメントを投稿