web-dev-qa-db-ja.com

PythonでGZIPモジュールを使用する

Python GZIPモジュールを使用して、ディレクトリ内のいくつかの.gzファイルを単純に圧縮解除しようとしています。ファイルを読み取らないで、圧縮解除するだけです。しばらくの間、私はこのコードセグメントを持っていますが、機能しません:

import gzip
import glob
import os
for file in glob.glob(PATH_TO_FILE + "/*.gz"):
    #print file
    if os.path.isdir(file) == False:
        shutil.copy(file, FILE_DIR)
        # uncompress the file
        inF = gzip.open(file, 'rb')
        s = inF.read()
        inF.close()

.gzファイルは正しい場所にあり、printコマンドでフルパス+ファイル名を印刷できますが、GZIPモジュールが正しく実行されていません。私は何が欠けていますか?

23
user3111358

エラーが表示されない場合、gzipモジュールはおそらく適切に実行されており、ファイルはすでに解凍されていますです。

「解凍」の正確な定義は、コンテキストによって異なります。

私はファイルを読みたくない、それらを解凍するだけ

gzipモジュールは、7-Zipのようなデスクトップアーカイブプログラムとしては機能しません。ファイルを「読み取る」ことなく「解凍」することはできません。 (プログラミングでの)「読み取り」とは、通常、「GUIでファイルを開く」ことではなく、「コンピューターのRAMに(一時的に)格納する」ことを意味します。

おそらく「解凍」(デスクトップアーカイブプログラムなど)の意味は、(プログラミングでは)「読み取り圧縮ファイルからのメモリ内ストリーム/バッファ、および新しいファイルへの書き込み(そして、圧縮ファイルを後で削除する可能性があります) "

inF = gzip.open(file, 'rb')
s = inF.read()
inF.close()

これらの行を使用すると、ストリームを読んでいるだけです。新しい「非圧縮」ファイルが作成されると予想される場合、バッファを新しいファイルに書き込むだけです

with open(out_filename, 'wb') as out_file:
    out_file.write(s)

非常に大きなファイル(RAMの容量よりも大きいファイル)を扱う場合は、別のアプローチを採用する必要があります。しかし、それは別の質問のトピックです。

40
goncalopp

withを使用してファイルを開き、もちろん、圧縮ファイルの読み取り結果を保存する必要があります。 gzip documentation を参照してください:

import gzip
import glob
import os
import os.path

for gzip_path in glob.glob("%s/*.gz" % PATH_TO_FILE):
    if not os.path.isdir(gzip_path):
        with gzip.open(gzip_path, 'rb') as in_file:
            s = in_file.read()

        # Now store the uncompressed data
        path_to_store = gzip_fname[:-3]  # remove the '.gz' from the filename

        # store uncompressed file data from 's' variable
        with open(path_to_store, 'w') as f:
            f.write(s)

正確に何をしたいかに応じて、 tarfile とその'r:gz'ファイルを開くためのオプション。

6
Martin Thoma

ファイルをs変数に解凍しますが、何もしません。 stackoverflowの検索を停止し、少なくともpythonチュートリアル。真剣に。

とにかく、コードにはいくつかの問題があります。

  1. 必要なのは、sの解凍されたデータを何らかのファイルに保存することです。

  2. 実際の*.gzファイルをコピーする必要はありません。コードでは、コピーではなく元のgzipファイルを展開しているためです。

  3. 予約語であるfileを変数として使用しています。これはエラーではなく、非常に悪い習慣です。

これはおそらくあなたが望むことをするはずです:

import gzip
import glob
import os
import os.path

for gzip_path in glob.glob(PATH_TO_FILE + "/*.gz"):
    if os.path.isdir(gzip_path) == False:
        inF = gzip.open(gzip_path, 'rb')
        # uncompress the gzip_path INTO THE 's' variable
        s = inF.read()
        inF.close()

        # get gzip filename (without directories)
        gzip_fname = os.path.basename(gzip_path)
        # get original filename (remove 3 characters from the end: ".gz")
        fname = gzip_fname[:-3]
        uncompressed_path = os.path.join(FILE_DIR, fname)

        # store uncompressed file data from 's' variable
        open(uncompressed_path, 'w').write(s)
5
Jan Spurny

サブプロセスモジュールを使用して、この問題を解決できました。

for file in glob.glob(PATH_TO_FILE + "/*.gz"):
    if os.path.isdir(file) == False:
        shutil.copy(file, FILE_DIR)
        # uncompress the file
        subprocess.call(["gunzip", FILE_DIR + "/" + os.path.basename(file)])

私の目標はアーカイブを単に解凍することだったので、上記のコードはこれを達成します。アーカイブファイルは中央の場所にあり、作業領域にコピーされ、圧縮されずにテストケースで使用されます。 GZIPモジュールは、私が達成しようとしていたものに対して複雑すぎました。

みんなの助けてくれてありがとう。それは大歓迎です!

4
user3111358

Opがディレクトリ内のすべてのファイルを抽出したいだけであるため、提示された他のソリューションよりもはるかに簡単なソリューションがあると思います。

import glob
from setuptools import archive_util

for fn in glob.glob('*.gz'):
  archive_util.unpack_archive(fn, '.')
0
Dalupus