diff --git a/src/epy_reader/ebooks/epub.py b/src/epy_reader/ebooks/epub.py index a8cf0fa..6e917ee 100644 --- a/src/epy_reader/ebooks/epub.py +++ b/src/epy_reader/ebooks/epub.py @@ -169,7 +169,7 @@ def initialize(self) -> None: assert relative_toc is not None relative_toc_path = relative_toc.get("href") assert relative_toc_path is not None - toc_path = self.root_dirpath + relative_toc_path + toc_path = os.path.normpath(os.path.join(self.root_dirpath, relative_toc_path)) toc = ET.parse(self.file.open(toc_path)).getroot() self.toc_entries = Epub._get_tocs(toc, version, contents) # *self.contents (absolute path) @@ -199,4 +199,5 @@ def get_img_bytestr(self, impath: str) -> Tuple[str, bytes]: return impath, self.file.read(impath) def cleanup(self) -> None: - pass + if isinstance(self.file, zipfile.ZipFile): + self.file.close() \ No newline at end of file diff --git a/src/epy_reader/reader.py b/src/epy_reader/reader.py index ee615f8..4eef043 100644 --- a/src/epy_reader/reader.py +++ b/src/epy_reader/reader.py @@ -147,7 +147,8 @@ def run_counting_letters(self): self._process_counting_letter = multiprocessing.Process( name="epy-subprocess-counting-letters", target=count_letters_parallel, - args=(copy.deepcopy(self.ebook), self._proc_child), + # Pass only the filepath, not the entire ebook object + args=(self.ebook.path, self._proc_child), ) # forking will raise # zlib.error: Error -3 while decompressing data: invalid distance too far back diff --git a/src/epy_reader/utils.py b/src/epy_reader/utils.py index bb24106..d3a7da6 100644 --- a/src/epy_reader/utils.py +++ b/src/epy_reader/utils.py @@ -4,6 +4,7 @@ import sys import textwrap from functools import wraps +from multiprocessing.connection import Connection from typing import List, Mapping, Optional, Sequence, Tuple, Union from epy_reader.ebooks import URL, Azw, Ebook, Epub, FictionBook, Mobi @@ -344,11 +345,10 @@ def construct_relative_reading_state( section=abs_reading_state.section, ) - def count_letters(ebook: Ebook) -> LettersCount: per_content_counts: List[int] = [] cumulative_counts: List[int] = [] - # assert isinstance(ebook.contents, tuple) + assert isinstance(ebook.contents, tuple) for i in ebook.contents: content = ebook.get_raw_text(i) src_lines = parse_html(content) @@ -358,11 +358,18 @@ def count_letters(ebook: Ebook) -> LettersCount: return LettersCount(all=sum(per_content_counts), cumulative=tuple(cumulative_counts)) - -def count_letters_parallel(ebook: Ebook, child_conn) -> None: - child_conn.send(count_letters(ebook)) - child_conn.close() - +def count_letters_parallel(filepath: str, conn: Connection): + """ + Counts letters in an ebook in a separate process. + Receives the ebook's filepath and a connection for sending results. + """ + # The child process opens its own ebook object + ebook_obj_in_child_process = get_ebook_obj(filepath) + ebook_obj_in_child_process.initialize() + letters_count = count_letters(ebook_obj_in_child_process) + ebook_obj_in_child_process.cleanup() + conn.send(letters_count) + conn.close() def construct_speaker( preferred: Optional[str] = None, args: List[str] = []