サイズの大きいファイルを書き出すスクリプトなど、実行中の環境でディスクの空き容量を取得したいときがあります。ここではPythonで、標準モジュールを使って空き容量を取得する方法を試してみたいと思います。
今回のサンプルを記載しておきます。一応Windows, Linux両方、かつPython2, Python3で動く、ようにしたつもりですが全てのパターンの検証はしていません。
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 30 31 32 33 34 35 36 37 38 39 40 41 42 | import os import platform import shutil from traceback import print_exc def available_capacity_mb(dir_path=os.getcwd()): # get available disk capacity for passed directory path print("path: {}".format(dir_path)) try: # try to use shutil return int(shutil.disk_usage(dir_path).free / 1024 / 1024) except: print("shutil.disk_usage() is not available") try: capacity_mb = 0 if 'Windows' in platform.uname(): import subprocess # parse fsutil command result buf = "fsutil volume diskfree {}".format(os.path.splitdrive(dir_path)[0]) buf = subprocess.check_output(buf).decode("cp932") buf = buf.split("\n")[0].split()[-1] # format as available megabytes capacity_mb = int(buf) / 1024 / 1024 else: # get stat and calculate available capacity stat = os.statvfs(dir_path) capacity_mb = stat.f_bsize * stat.f_bfree / 1024 / 1024 return int(capacity_mb) except: print_exc() # returns negative in failure case return -1 if __name__ == "__main__": print("{:,d}[MB]".format(available_capacity_mb())) print("{:,d}[MB]".format(available_capacity_mb("D:"))) |
実装はavailable_capacity_mb
関数で、引数は調べたいパス(ディレクトリへのパス)です。
デフォルトはos.getcwd()
で実行中のディレクトリを渡しています。
Python3での空き容量取得
Python3.3からはshutil.disk_usage()
が実装されているので、素直にこれを使います。
1 | return int(shutil.disk_usage(dir_path).free / 1024 / 1024) |
さて、その他のバージョンでは代替手段を考える必要があります。
Windowsでの空き容量取得
標準モジュールで、と言いつつあまりよろしくない方法で実装しています。
要はsubprocess
でWindowsのfsutil
コマンドを呼び出し、返ってきた標準出力をパースする、という動きにしています。
1 2 3 | buf = "fsutil volume diskfree {}".format(os.path.splitdrive(dir_path)[0]) buf = subprocess.check_output(buf).decode("cp932") buf = buf.split("\n")[0].split()[-1] |
fsutil
…コマンド出力の一行目が「空きバイト総数」。なので、出力をShift-JISでデコードし、改行文字で分割して一行目を取り出し、さらに分割してその行の最後の数字を取り出す、というかなり環境依存のやり方です。
Linuxでの空き容量取得
Linuxではos.statvfs()
が使えるので、上のWindowsでの例よりはマシな実装です。
1 2 | stat = os.statvfs(dir_path) capacity_mb = stat.f_bsize * stat.f_bfree / 1024 / 1024 |
MB(メガバイト)での出力を得るために除算しています。
Windowsと違って権限の制御は厳密なので、アクセスが許可されていないパスを指定するとエラーを吐きます。
テスト
実行結果はこんな感じ。Windows環境(Windows 10 Pro + Python 3.6)で実行した例です。
1 2 3 4 5 | > python get_free_capacity.py path: C:\path\to\current\dir 412,708[MB] path: D: 853,125[MB] |
ちなみに実在しないパスを指定するとエラーになります。
1 2 3 4 5 6 7 8 9 10 | path: X: Traceback (most recent call last): File "get_free_capacity.py", line 17, in available_capacity_mb buf = subprocess.check_output(buf).decode("cp932") File "...\lib\subprocess.py", line 336, in check_output **kwargs).stdout File "...\lib\subprocess.py", line 418, in run output=stdout, stderr=stderr) subprocess.CalledProcessError: Command 'fsutil volume diskfree X:' returned non-zero exit status 1. -1[MB] |
上の例では、fsutil
コマンドの終了ステータスコードが失敗(non-zero)であることをメッセージで示しています。