Pythonでctypesやらwin32apiを使ってドライブの空き容量を調べるサンプル

bonlifeです。久しぶりにPythonに触れてみました。

コピーするフォルダーの容量は、os.walkを使って取得できました が、ドライブの空き容量の求め方がわかりません。仕方がないので、dirコマンドの出力を正規表現で切り出してみました。日本語の正規表現がわからないので、dos窓を英語モードにしてからdirコマンドを発行しています。

なんだかあんまりスマートじゃないやり方…。こういうことは、Windowsに直接語りかければ答えが返ってくるはず!ということで調べてみると、GetDiskFreeSpaceExというものがありました。以下のような関数らしい。lpDirectoryName を指定して実行するとアレコレ情報が取得できるみたい。

BOOL GetDiskFreeSpaceEx(
  LPCTSTR lpDirectoryName,                 // ディレクトリ名
  PULARGE_INTEGER lpFreeBytesAvailable,    // 呼び出し側が利用できるバイト数
  PULARGE_INTEGER lpTotalNumberOfBytes,    // ディスク全体のバイト数
  PULARGE_INTEGER lpTotalNumberOfFreeBytes // ディスク全体の空きバイト数
);

ctypesを使ってみる

こういうのはctypes使うと良いってどこかで見かけたことがあったので、ctypesとGetDiskFreeSpaceExを元にGoogle先生にお伺いをたてたところ、まさにッ!なページを発見。

http://www.python-forum.org/pythonforum/viewtopic.php?f=18&t=9461#p43424

このままだとドライブを指定できなかったり、戻り値が ctypes.c_ulonglong で扱いづらかったりするので、少しだけ修正してみました。(失敗した場合の処理は省略。)

>>> from ctypes import *
>>> def free_disk_space(drive=None):
	free_bytes_available       = c_ulonglong()
	total_number_of_bytes      = c_ulonglong()
	total_number_of_free_bytes = c_ulonglong()
	a = windll.kernel32.GetDiskFreeSpaceExA(
		drive,
		byref(free_bytes_available),
		byref(total_number_of_bytes),
		byref(total_number_of_free_bytes)
	)
	return free_bytes_available.value, total_number_of_bytes.value, total_number_of_free_bytes.value

>>> free_disk_space('C:')
(397914681344L, 483934597120L, 397914681344L)
>>> free_disk_space()
(397914681344L, 483934597120L, 397914681344L)
>>> for i in free_disk_space('C:'):
	print i / (1024 ** 3), "GB"

370 GB
450 GB
370 GB

win32apiを使ってみる

ただ、pywin32をインストールしてwin32apiを使うと遥かに簡単に同じことが出来ちゃいます。

>>> import win32api
>>> win32api.GetDiskFreeSpaceEx('C:')
(397914681344L, 483934597120L, 397914681344L)
>>> for i in win32api.GetDiskFreeSpaceEx():
	print i / (1024 ** 3), "GB"

	
370 GB
450 GB
370 GB

楽過ぎる。pywin32は今日インストールしてはじめて使ってみましたが、IDLEでの補完も利くし、色々と遊べそうですね。

まとめ

スクレイピング的な処理をせずに情報を取得できないか調べてみたことで、bonlifeの視界が広がりましたとさ。Windowsの操作で何か困った時、今回の経験が活きますように。