Использование модуля GZIP с Python

Я пытаюсь использовать модуль 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 находятся в правильном месте, и я могу напечатать полный путь + имя файла с помощью команды печати, но модуль GZIP не выполняется должным образом. что мне не хватает?


person user3111358    schedule 17.12.2013    source источник
comment
Файл в порядке? Вы не показываете, что происходит/не происходит.   -  person f p    schedule 17.12.2013
comment
Да, файл в порядке. Я могу распаковать файл с помощью gunzip в командной строке UNIX.   -  person user3111358    schedule 17.12.2013


Ответы (5)


Если вы не получили сообщения об ошибке, вероятно, модуль gzip выполняется правильно, и файл уже распаковывается.

Точное определение «распакованного» зависит от контекста:

Я не хочу читать файлы, только распаковать их

Модуль gzip не работает как настольная программа архивации, как 7-zip — вы не можете «распаковать» файл, не «прочитав» его. Обратите внимание, что «чтение» (в программировании) обычно означает просто «сохранение (временное) в оперативной памяти компьютера», а не «открытие файла в графическом интерфейсе».

То, что вы вероятно подразумеваете под "распаковкой" (как в настольной программе архивирования), более точно описывается (в программировании) как "чтение потока/буфера в памяти из сжатого файла и записать его в новый файл (и, возможно, впоследствии удалить сжатый файл)"

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

С этими строками вы просто читаете поток. Если вы ожидаете, что будет создан новый «несжатый» файл, вам просто нужно записать буфер в новый файл:

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

Если вы имеете дело с очень большими файлами (больше, чем объем вашей оперативной памяти), вам придется применить другой подход. Но это тема для другого вопроса.

person loopbackbee    schedule 17.12.2013
comment
Когда я запускаю скрипт Python, ошибок не возникает, но файл gzip не распаковывается. Я только хочу распаковать файл, чтобы его можно было использовать в другом инструменте, а не переписывать в файл или использовать где-то еще в моем сценарии. - person user3111358; 17.12.2013
comment
@user3111358 user3111358 Что значит, точно файл gzip не несжатый? Что заставляет тебя так говорить? Вы проверили содержимое s в своем коде? - person loopbackbee; 17.12.2013
comment
Я имею в виду, что файл gzip не несжатый, что я и пытаюсь сделать. Я ТОЛЬКО хочу распаковать, ничего больше. - person user3111358; 17.12.2013
comment
@ user3111358 Я пытаюсь сказать, что распаковка означает разные вещи в разных контекстах. Могу поспорить, что если вы спросите нескольких человек, которые читали ваш код здесь, на SO, они скажут вам, что файл разархивирован. Таким образом, я должен спросить: откуда вы знаете, что файл не распаковывается? Это потому, что новые файлы не помещаются в тот же каталог, что и сжатый файл, когда вы запускаете код? - person loopbackbee; 17.12.2013
comment
Это правильный ответ. Когда вы распаковываете файл, он записывается в новый файл, а предыдущий сжатый файл либо удаляется как другое действие, либо сжатый файл сохраняется. В любом случае записывается новый несжатый файл. - person sage88; 14.08.2015

Вы должны использовать with для открытия файлов и, конечно же, для сохранения результата чтения сжатого файла. См. gzip документацию:

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' для открытия файлов.

person Martin Thoma    schedule 12.10.2015
comment
Было бы лучше использовать os.path.splitext(gzip_fname)[0] для удаления расширения .gz - person Gauthier; 05.04.2016
comment
ваш пример неверен, gzip_fname не существует, вы должны изменить его на gzip_path. Кроме того, то, что вы получаете в gzip_path, — это не путь, а файл gz. Поэтому вы должны изменить os.path.isdir на os.path.isfile Я также думаю, что лучше использовать решение @gotson :) - person hoaphumanoid; 23.08.2016

Вы распаковываете файл в переменную 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)
person Jan Spurny    schedule 17.12.2013
comment
Когда вы вызываете open(uncompressed_path, 'w').write(s) без назначения обработчика файла переменной, нет необходимости закрывать обработчик файла? - person Ander; 31.01.2017
comment
@Ander - да, потому что (анонимный) файловый объект никогда не будет присвоен переменной и, следовательно, будет уничтожен сразу после выполнения. Я считаю, что гораздо чище простая запись xy в файл или чтение из файла, то есть когда есть ровно одно чтение или запись. Но если вы выполняете более одного чтения/записи, вам, вероятно, всегда следует использовать with open(...): - person Jan Spurny; 31.01.2017

Я смог решить эту проблему с помощью модуля подпроцесса:

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 был слишком сложен для того, что я пытался сделать.

Спасибо всем за помощь. Это очень ценится!

person user3111358    schedule 17.12.2013
comment
Да, если вам не нужно программно манипулировать содержимым кода и вас не смущает, что он несовместим между операционными системами, то это гораздо более интуитивный способ подхода к вещам. - person ChrisGuest; 02.04.2019

Я думаю, что есть гораздо более простое решение, чем другие представленные, учитывая, что оператор хотел только извлечь все файлы в каталоге:

import glob
from setuptools import archive_util

for fn in glob.glob('*.gz'):
  archive_util.unpack_archive(fn, '.')
person Dalupus    schedule 03.04.2016
comment
Archive_util.unpack_archive, похоже, не поддерживает .gz. Сообщение об ошибке: setuptools.archive_util.UnrecognizedFormat: не распознанный тип архива: K:\z_temp\file.gz. Также Shutil.upack_archive не поддерживает .gz. Чтобы увидеть поддерживаемые типы файлов для Shutil_unpack_archive: import shutil; print(shutil.get_archive_formats()) - person punchcard; 13.07.2016