извлечение сжатых файлов из расширения .gz при их загрузке с ftp-сервера [дубликат]

Aug 20 2020

Я создал функцию, которая загружает файлы .gz с данного ftp-сервера, и я хочу извлекать их на лету при загрузке и удалении сжатых файлов впоследствии. Как я могу это сделать?

sinex_domain = "ftp://cddis.gsfc.nasa.gov/gnss/products/bias/2013"

def download(sinex_domain):
    user = getpass.getuser()
    sinex_parse = urlparse(sinex_domain)

    sinex_connetion = FTP(sinex_parse.netloc)
    sinex_connetion.login()
    sinex_connetion.cwd(sinex_parse.path)
    sinex_files = sinex_connetion.nlst()
    sinex_userpath = "C:\\Users\\" + user + "\\DCBviz\\sinex"
    pathlib.Path(sinex_userpath).mkdir(parents=True, exist_ok=True)

    for fileName in sinex_files:
        local_filename = os.path.join(sinex_userpath, fileName)
        file = open(local_filename, 'wb')
        sinex_connetion.retrbinary('RETR '+ fileName, file.write, 1024)
        
        #want to extract files in this loop

        file.close()

    sinex_connetion.quit()

download(sinex_domain)

Ответы

1 alani Aug 20 2020 at 02:09

Хотя, вероятно, есть более умный способ, позволяющий избежать хранения всех данных в памяти для каждого файла, они кажутся довольно небольшими файлами (несколько десятков килобайт без сжатия), поэтому было бы достаточно прочитать сжатые данные в BytesIOбуфер, а затем распаковать его в памяти перед записью в выходной файл. (Сжатые данные никогда не сохраняются на диск.)

Вы бы добавили этот импорт:

import gzip
from io import BytesIO

а затем ваш основной цикл станет:

    for fileName in sinex_files:
        local_filename = os.path.join(sinex_userpath, fileName)
        if local_filename.endswith('.gz'):
            local_filename = local_filename[:-3]
        data = BytesIO()
        sinex_connetion.retrbinary('RETR '+ fileName, data.write, 1024)
        data.seek(0)
        uncompressed = gzip.decompress(data.read())
        with open(local_filename, 'wb') as file:
            file.write(uncompressed)

(Обратите внимание, что file.close()это не нужно.)