Скачайте Zip файл с FTP в память и распакуйте его - PullRequest
1 голос
/ 14 октября 2019

Я пытаюсь создать функцию, которая загружает файл с FTP в память и возвращает его. В этом случае я пытаюсь загрузить ZIP-файл и разархивировать его, не записывая файл локально, но получаю следующую ошибку:

ValueError: I/O operation on closed file.

Вот мой текущий код:

from io import BytesIO
from ftplib import FTP_TLS

def download_from_ftp(fp):
    """
    Retrieves file from a ftp
    """
    ftp_host = 'some ftp url'
    ftp_user = 'ftp username'
    ftp_pass = 'ftp password'

    with FTP_TLS(ftp_host) as ftp:
        ftp.login(user=ftp_user, passwd=ftp_pass)
        ftp.prot_p()
        with BytesIO() as download_file:
            ftp.retrbinary('RETR ' + fp, download_file.write)
            download_file.seek(0)
            return download_file

А вот мой код, который пытается разархивировать файл:

import zipfile
from ftp import download_from_ftp

ftp_file = download_from_ftp('ftp zip file path')
with zipfile.ZipFile(ftp_file, 'r') as zip_ref:
    # do some stuff with files in the zip

1 Ответ

2 голосов
/ 14 октября 2019

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

Вы можете просто назначитьвместо этого BytesIO создает переменную для возврата. Измените:

with BytesIO() as download_file:

на:

download_file = BytesIO()

и выделите блок.

...