Pythonでtar.gzなファイルを解凍(展開)する

Pythonでtar.gzで圧縮されたファイルを解凍(展開)してみます。

目次

  1. tarfileモジュールでtar.gzファイルを扱う
  2. 使用するメソッド
  3. 展開の実施例

tarfileモジュールでtar.gzファイルを扱う

拡張子がtar.gzなファイルというのは、tarというツールでファイルをひとまとめにして、gzipで圧縮したファイルです。

Windowsではzipがメインですが、Linuxがらみのファイルをいじるようになるとダウンロードしたデータがtar.gzになっていることがよくあります。Linuxならgzipで展開できます。Windows10にはtarは標準でインストールされているのですがgzipがありません。

7zipを使えばこのファイルを展開できるのですが、そのためだけに7zipをインストールするのも面倒です。

そこで、Pythonで展開することにしました。

Pythonのtarfileモジュールがtarでgzなファイルの展開に対応しています。標準モジュールなので、Python3が入っていればpipも要りません。

使用するメソッド

tarfile.openメソッド

t = tarfile.open(name, [mode], [fileobj], [bufsize])
変数 内容
name str ファイルのパス。
mode str 省略可。規定値はr。ファイルアクセスするモード。
fileobj str 省略可。規定値はNone。
bufsize int 省略可。規定値は10240。
t TarFile 指定されたファイルパスのTarFileオブジェクト。

modeの例

r 圧縮方法に関して透過的に、読み込み専用にオープンする。
x 圧縮せずにtarfileを作成する。ファイルが既存の場合はエラー。
a 圧縮せずにtarfileを追記用にオープンする。
w 非圧縮で書き込み用にオープンする。
w:gz gzip圧縮で書き込み用にオープンする。

ファイルをオープンするメソッドです。読み込みでも書き込みでも使います。展開の時はファイルパスだけ指定すればOKですね。

Openで得られたTarFileオブジェクトに対して、展開の操作をします。

TarFile.extractallメソッド

t.extractall([path], [members], [numeric_owner])
変数 内容
t TarFile 展開の対象となるオープン済みのTarFileオブジェクト。
path str 省略可。規定値は.。展開先のディレクトリ。
members list 省略可。規定値はNone。
numeric_owner bool 省略可。規定値はFalse。

ファイルを展開します。pathを設定しない場合は、作業ディレクトリに展開します。

ここで注意なのは、展開先が作業フォルダ以下に限らないということです。圧縮ファイル内のファイルのパスがルートに指定されている場合は、ルートに展開されます。

そこで、圧縮ファイルに格納されているファイルのパスを調べてみます。

TarFile.getmembersメソッド

L = T.getmenbers()
変数 内容
T TarFile 展開の対象となるオープン済みのTarFileオブジェクト。
L list 圧縮ファイルに含まれているメンバーのリストを返します。

戻り値がTarInfoというオブジェクトのリストになります。リスト内の各TarInfoオブジェクトのnameプロパティにアクセスすると、ファイルのパスが得られます。

展開の実施例

展開するときの処理の順番としては、次のようになります。

  1. tarfile.openメソッドでファイルをオープンする。
  2. TarFile.getmenbersメソッドで、圧縮ファイル内のファイルのパスがカレントディレクトリ以下かどうか調べる。
  3. TarFile.extractallメソッドで展開する。

では実際に試してみます。

tar.gzなファイルとしては、onnx model zooからダウンロードしたmnist.tar.gzにしてみます。

import tarfile
with tarfile.open('mnist.tar.gz') as tar:
    for i in tar.getmembers():
        if i.name[0] == '/' or i.name[0:2] == '..':
            print('外のディレクトリに展開されるかも。')
            exit()
    tar.extractall()
>dir /s /b
C:\mnist
C:\mnist.tar.gz
C:\mnist\model.onnx
C:\mnist\test_data_set_0
C:\mnist\test_data_set_1
C:\mnist\test_data_set_2
C:\mnist\test_data_set_0\input_0.pb
C:\mnist\test_data_set_0\output_0.pb
C:\mnist\test_data_set_1\input_0.pb
C:\mnist\test_data_set_1\output_0.pb
C:\mnist\test_data_set_2\input_0.pb
C:\mnist\test_data_set_2\output_0.pb

もうちょっとPython的にエレガントに書く方法がありそうですが、まあ動いたのでよしとします。

広告

Pythonカテゴリの投稿