From e1e6d587f4298b152c79f89fb202dc6bc4169e81 Mon Sep 17 00:00:00 2001 From: Alex Xu Date: Sun, 2 Mar 2025 11:08:27 -0800 Subject: [PATCH] makeZIP now prefers 7z for SPEED (#844) --- kindlecomicconverter/KCC_gui.py | 21 ++++++---------- kindlecomicconverter/comic2ebook.py | 38 +++++++++++++++++------------ kindlecomicconverter/shared.py | 14 +++++++++++ 3 files changed, 44 insertions(+), 29 deletions(-) diff --git a/kindlecomicconverter/KCC_gui.py b/kindlecomicconverter/KCC_gui.py index a4622d5..d18cea9 100644 --- a/kindlecomicconverter/KCC_gui.py +++ b/kindlecomicconverter/KCC_gui.py @@ -37,7 +37,7 @@ from packaging.version import Version from raven import Client from tempfile import gettempdir -from .shared import HTMLStripper, sanitizeTrace, walkLevel, subprocess_run +from .shared import HTMLStripper, available_archive_tools, sanitizeTrace, walkLevel, subprocess_run from . import __version__ from . import comic2ebook from . import metadata @@ -1066,19 +1066,12 @@ class KCCGUI(KCC_ui.Ui_mainWindow): self.addMessage('Since you are a new user of KCC please see few ' 'important tips.', 'info') - try: - subprocess_run(['tar'], stdout=PIPE, stderr=STDOUT) - self.tar = True - except FileNotFoundError: - self.tar = False - try: - subprocess_run(['7z'], stdout=PIPE, stderr=STDOUT) - self.sevenzip = True - except FileNotFoundError: - self.sevenzip = False - if not self.tar: - self.addMessage('Install 7z (link)' - ' to enable CBZ/CBR/ZIP/etc processing.', 'warning') + + self.tar = 'tar' in available_archive_tools() + self.sevenzip = '7z' in available_archive_tools() + if not any([self.tar, self.sevenzip]): + self.addMessage('Install 7z (link)' + ' to enable CBZ/CBR/ZIP/etc processing.', 'warning') self.detectKindleGen(True) APP.messageFromOtherInstance.connect(self.handleMessage) diff --git a/kindlecomicconverter/comic2ebook.py b/kindlecomicconverter/comic2ebook.py index 9c02f4a..fef6fcf 100755 --- a/kindlecomicconverter/comic2ebook.py +++ b/kindlecomicconverter/comic2ebook.py @@ -23,7 +23,7 @@ import pathlib import re import sys from argparse import ArgumentParser -from time import strftime, gmtime +from time import perf_counter, strftime, gmtime from copy import copy from glob import glob, escape from re import sub @@ -40,7 +40,7 @@ from subprocess import STDOUT, PIPE from psutil import virtual_memory, disk_usage from html import escape as hescape -from .shared import md5Checksum, getImageFileName, walkSort, walkLevel, sanitizeTrace, subprocess_run +from .shared import available_archive_tools, md5Checksum, getImageFileName, walkSort, walkLevel, sanitizeTrace, subprocess_run from . import comic2panel from . import image from . import comicarchive @@ -946,17 +946,27 @@ def slugify(value): def makeZIP(zipfilename, basedir, isepub=False): + start = perf_counter() zipfilename = os.path.abspath(zipfilename) + '.zip' - zipOutput = ZipFile(zipfilename, 'w', ZIP_DEFLATED) - if isepub: - zipOutput.writestr('mimetype', 'application/epub+zip', ZIP_STORED) - for dirpath, _, filenames in os.walk(basedir): - for name in filenames: - path = os.path.normpath(os.path.join(dirpath, name)) - aPath = os.path.normpath(os.path.join(dirpath.replace(basedir, ''), name)) - if os.path.isfile(path): - zipOutput.write(path, aPath) - zipOutput.close() + if '7z' in available_archive_tools(): + if isepub: + mimetypeFile = open(os.path.join(basedir, 'mimetype'), 'w') + mimetypeFile.write('application/epub+zip') + mimetypeFile.close() + subprocess_run(['7z', 'a', '-tzip', zipfilename, basedir], capture_output=True, check=True) + else: + zipOutput = ZipFile(zipfilename, 'w', ZIP_DEFLATED) + if isepub: + zipOutput.writestr('mimetype', 'application/epub+zip', ZIP_STORED) + for dirpath, _, filenames in os.walk(basedir): + for name in filenames: + path = os.path.normpath(os.path.join(dirpath, name)) + aPath = os.path.normpath(os.path.join(dirpath.replace(basedir, ''), name)) + if os.path.isfile(path): + zipOutput.write(path, aPath) + zipOutput.close() + end = perf_counter() + print(f"makeZIP time: {end - start} seconds") return zipfilename @@ -1131,9 +1141,7 @@ def checkTools(source): source = source.upper() if source.endswith('.CB7') or source.endswith('.7Z') or source.endswith('.RAR') or source.endswith('.CBR') or \ source.endswith('.ZIP') or source.endswith('.CBZ'): - try: - subprocess_run(['7z'], stdout=PIPE, stderr=STDOUT) - except FileNotFoundError: + if '7z' not in available_archive_tools(): print('ERROR: 7z is missing!') sys.exit(1) if options.format == 'MOBI': diff --git a/kindlecomicconverter/shared.py b/kindlecomicconverter/shared.py index d98c5de..76c579f 100644 --- a/kindlecomicconverter/shared.py +++ b/kindlecomicconverter/shared.py @@ -18,6 +18,7 @@ # PERFORMANCE OF THIS SOFTWARE. # +from functools import lru_cache import os from hashlib import md5 from html.parser import HTMLParser @@ -137,6 +138,19 @@ def dependencyCheck(level): print('ERROR: ' + ', '.join(missing) + ' is not installed!') sys.exit(1) +@lru_cache +def available_archive_tools(): + available = [] + + for tool in ['tar', '7z', 'unar', 'unrar']: + try: + subprocess_run([tool], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + available.append(tool) + except FileNotFoundError: + pass + + return available + def subprocess_run(command, **kwargs): if (os.name == 'nt'): kwargs.setdefault('creationflags', subprocess.CREATE_NO_WINDOW)