简体   繁体   中英

Unexpected end of data when zipping zip files in Python

Good day.

I wrote a little Python program to help me easily create.cbc files for Calibre, which is just a renamed.zip file with a text file called comics.txt for TOC purposes. Each chapter is another zip file.

The issue is that the last zip file zipped always has the error "Unexpected end of data". The file itself is not corrupt, if I unzip it and rezip it it works perfectly. Playing around it seems that the problem is that Python doesn't close the last zip file after zipping it, since I can't delete the last zip while the program is still running since it's still open in Python. Needless to say, Calibre doesn't like the file and fails to convert it unless I manually rezip the affected chapters.

The code is as follows, checking the folders for not-image files, zipping the folders, zipping the zips while creating the text file, and "changing" extension.


import re, glob, os, zipfile, shutil, pathlib, gzip, itertools

Folders = glob.glob("*/")
items = len(Folders)
cn_list = []
cn_list_filtered = []
dirs_filtered = []
ch_id = ["c", "Ch. "]
subdir_im = []
total = 0
Dirs = next(os.walk('.'))[1]

for i in range(0, len(Dirs)):
    for items in os.listdir("./" + Dirs[i]):
        if items.__contains__('.png') or items.__contains__('.jpg'):
            total+=1
        else:
            print(items + " not an accepted format.")
    subdir_im.append(total)
    total = 0

for fname in Folders:
    if re.search(ch_id[0] + r'\d+' + r'[\S]' + r'\d+', fname):
        cn = re.findall(ch_id[0] + "(\d+[\S]\d+)", fname)[0]
        cn_list.append(cn)
    elif re.search(ch_id[0] + r'\d+', fname):
        cn = re.findall(ch_id[0] + "(\d+)", fname)[0]
        cn_list.append(cn)
    elif re.search(ch_id[1] + r'\d+' + '[\S]' + r'\d+', fname):
        cn = re.findall(ch_id[1] + "(\d+[\S]\d+)", fname)[0]
        cn_list.append(cn)
    elif re.search(ch_id[1] + r'\d+', fname):
        cn = re.findall(ch_id[1] + "(\d+)", fname)[0]
        cn_list.append(cn)
    else:
        print('Warning: File found without proper filename format.')

cn_list_filtered = set(cn_list)
cn_list_filtered = sorted(cn_list_filtered)

cwd = os.getcwd()
Dirs = Folders
subdir_zi = []
total = 0

for i in range(0, len(cn_list_filtered)):
    for folders in Dirs:
        if folders.__contains__(ch_id[0] + cn_list_filtered[i] + " ")\
         or folders.__contains__(ch_id[1] + cn_list_filtered[i] + " "):
            print('Zipping folder ', folders)
            namezip = "Chapter " + cn_list_filtered[i] + ".zip"
            current_zip = zipfile.ZipFile(namezip, "a")
            for items in os.listdir(folders):
                if items.__contains__('.png') or items.__contains__('.jpg'):
                    current_zip.write(folders + "/" + items, items)
                    total+=1
    subdir_zi.append(total)
    total = 0

print('Folder contents in order:', subdir_im, ' Total:', sum(subdir_im))
print("Number of items per zip: ", subdir_zi, ' Total:', sum(subdir_zi))

if subdir_im == subdir_zi:
    print("All items in folders have been successfully zipped")
else:
    print("Warning: File count in folders and zips do not match. Please check the affected chapters")

zips = glob.glob("*.zip")

namezip2 = os.path.basename(os.getcwd()) + ".zip"
zipfinal = zipfile.ZipFile(namezip2, "a")

for i in range(0, len(zips), 1):
    zipfinal.write(zips[i],zips[i])

Data = []

for i in range (0,len(cn_list_filtered),1):
    Datai = ("Chapter " + cn_list_filtered[i] + ".zip" + ":Chapter " + cn_list_filtered[i] + "\r\n")
    Data.append(Datai)

Dataok = ''.join(Data)

with zipfile.ZipFile(namezip2, 'a') as myzip:
    myzip.writestr("comics.txt", Dataok)

zipfinal.close()

os.rename(namezip2, namezip2 + ".cbc")

os.system("pause")

I am by no means a programmer, that is just a Frankenstein monster code I eventually managed to put together by checking threads, but this last issue has me stumped.

Some solutions I tried are:

for i in range(0, len(zips), 1):
    zipfinal.write(zips[i],zips[i])
    zips[i].close()

Fails with:

zips[i].close()
AttributeError: 'str' object has no attribute 'close'

and:

for i in range(0, len(zips), 1):
    zipfinal.write(zips[i],zips[i])

zips[len(zips)].close()

Fails with:

    zips[len(zips)].close()
IndexError: list index out of range

Thanks for the help.

This solved my issue:

def generate_zip(file_list, file_name=None):
    zip_buffer = io.BytesIO()
    zf = zipfile.ZipFile(zip_buffer, mode="w", compression=zipfile.ZIP_DEFLATED)
    for file in file_list:
        print(f"Filename: {file[0]}\nData: {file[1]}")
        zf.writestr(file[0], file[1])
    **zf.close()**
    with open(file_name, 'wb') as f:
        f.write(zip_buffer.getvalue())
        f.close()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM