Как прочитать файл gzip netcdf в python?

У меня есть работающая программа на Python, которая считывает несколько больших файлов netCDF с помощью команды Dataset из модуля netCDF4. Вот фрагмент соответствующих частей:

from netCDF4 import Dataset
import glob

infile_root = 'start_of_file_name_'

for infile in sorted(glob.iglob(infile_root + '*')):
   ncin = Dataset(infile,'r')
   ncin.close()

Я хочу изменить это для чтения в файлах netCDF, которые сжаты gzip. Сами файлы были сжаты после создания; они не сжаты внутри (т. е. файлы имеют формат *.nc.gz). Если бы я читал текстовые файлы, сжатые gzip, команда была бы такой:

from netCDF4 import Dataset
import glob
import gzip

infile_root = 'start_of_file_name_'

for infile in sorted(glob.iglob(infile_root + '*.gz')):
   f = gzip.open(infile, 'rb')
   file_content = f.read()
   f.close()

Погуглив около получаса и прочитав документацию netCDF4, я нашел единственный способ сделать это для файлов netCDF:

from netCDF4 import Dataset
import glob
import os

infile_root = 'start_of_file_name_'

for infile in sorted(glob.iglob(infile_root + '*.gz')):
   os.system('gzip -d ' + infile)
   ncin = Dataset(infile[:-3],'r')
   ncin.close()
   os.system('gzip ' + infile[:-3]) 

Можно ли напрямую читать файлы gzip с помощью команды Dataset? Или без вызова gzip через os?


person eclark    schedule 05.12.2014    source источник
comment
В документах набора данных ничего не указано. о файлах gz, поэтому я не думаю, что это поддерживается. Я уверен, что есть способ распаковать их изнутри Python без системного вызова gzip, но я не знаю, что это будет. Зачем вам нужно, чтобы он обрабатывался Dataset?   -  person Spencer Hill    schedule 05.12.2014
comment
Я не хотел делать отдельные вызовы для распаковки, а затем повторно архивировать файлы. Я также в основном хочу избежать системного вызова.   -  person eclark    schedule 05.12.2014
comment
gzip.open возвращает файлоподобный объект, который можно использовать для доступа к файлу только для чтения, но похоже, что netCDF4 этого не поддерживает. Если бы это был я, я бы использовал модуль python gzip, чтобы разархивировать во временный файл и оставить оригинал в покое. Если это нужно делать часто, вы можете начать поддерживать кеш тех файлов, которые вы разархивировали. Если файлы изменены, вам все равно нужно распаковать и снова заархивировать, так что, черт возьми.   -  person tdelaney    schedule 05.12.2014
comment
@tdelaney - Спасибо. Использование модуля gzip для распаковки во временные файлы — отличное предложение.   -  person eclark    schedule 05.12.2014


Ответы (3)


Поскольку NetCDF4-Python является оболочкой библиотеки C NetCDF4, вам не повезло, если вы используете модуль gzip для передачи файлового объекта. Единственный вариант, как предложил @tdelaney, использовать gzip для извлечения во временный файл.

Если у вас есть какой-либо контроль над созданием этих файлов, файлы NetCDF версии 4 поддерживают внутреннее сжатие zlib, поэтому использование gzip является излишним. Также может быть целесообразно преобразовать файлы из версии 3 в версию 4, если вам нужно повторно обрабатывать эти файлы.

person DopplerShift    schedule 05.12.2014

Чтение наборов данных из памяти поддерживается начиная с netCDF4-1.2.8 (Журнал изменений) :

import netCDF4
import gzip

with gzip.open('test.nc.gz') as gz:
    with netCDF4.Dataset('dummy', mode='r', memory=gz.read()) as nc:
        print(nc.variables)

См. описание параметра memory в Dataset документации.

person sfinkens    schedule 01.08.2018

Так как мне как раз нужно было решить такую ​​же задачу, вот готовое решение:

import gzip
import os
import shutil
import tempfile

import netCDF4

def open_netcdf(fname):
    if fname.endswith(".gz"):
        infile = gzip.open(fname, 'rb')
        tmp = tempfile.NamedTemporaryFile(delete=False)
        shutil.copyfileobj(infile, tmp)
        infile.close()
        tmp.close()
        data = netCDF4.Dataset(tmp.name)
        os.unlink(tmp.name)
    else:
        data = netCDF4.Dataset(fname)
    return data
person jochen    schedule 27.07.2017