From cfd67ab6aab8199497d623ba069f786936c10439 Mon Sep 17 00:00:00 2001 From: "James R. Barlow" Date: Fri, 17 May 2019 14:24:47 -0700 Subject: [PATCH] Fixing threading._RLock exception on Python 3.6 Issue was the usual business: objects that cross process boundaries need to be picklable and Python 3.6 is more strict about this. The logger object in particular interfered, so now we suppress it and rebuild it in process. --- src/ocrmypdf/_jobcontext.py | 50 ++++++++++++++++++++++++++++--------- src/ocrmypdf/_sync.py | 12 +++------ 2 files changed, 42 insertions(+), 20 deletions(-) diff --git a/src/ocrmypdf/_jobcontext.py b/src/ocrmypdf/_jobcontext.py index bef45426..cc23de85 100644 --- a/src/ocrmypdf/_jobcontext.py +++ b/src/ocrmypdf/_jobcontext.py @@ -22,10 +22,29 @@ import os from contextlib import suppress -class PDFContext: +class PicklableLoggerMixin: + def __init__(self): + self._log = None + + @property + def log(self): + if not self._log: + self._log = self.get_logger() + return self._log + + def __getstate__(self): + log = self._log + self._log = None + state = self.__dict__ + self._log = log + return state + + +class PDFContext(PicklableLoggerMixin): """Holds our context for a particular run of the pipeline""" def __init__(self, options, work_folder, origin, pdfinfo): + PicklableLoggerMixin.__init__(self) self.options = options self.work_folder = work_folder self.origin = origin @@ -36,7 +55,9 @@ class PDFContext: self.name = 'origin.pdf' if self.name == '-': self.name = 'stdin' - self.log = get_logger(options, filename=self.name) + + def get_logger(self): + return make_logger(self.options, filename=self.name) def get_path(self, name): return os.path.join(self.work_folder, name) @@ -47,22 +68,27 @@ class PDFContext: yield PageContext(self, n) -class PageContext: - """Holds our context for a page""" +class PageContext(PicklableLoggerMixin): + """Holds our context for a page + + Must be pickable, so only store intrinsic/simple data elements + """ def __init__(self, pdf_context, pageno): - self.pdf_context = pdf_context + PicklableLoggerMixin.__init__(self) + self.work_folder = pdf_context.work_folder + self.origin = pdf_context.origin self.options = pdf_context.options + self.name = pdf_context.name self.pageno = pageno self.pageinfo = pdf_context.pdfinfo[pageno] - self.log = get_logger( - pdf_context.options, filename=self.pdf_context.name, page=(self.pageno + 1) - ) + self._log = None + + def get_logger(self): + return make_logger(self.options, filename=self.name, page=self.pageno + 1) def get_path(self, name): - return os.path.join( - self.pdf_context.work_folder, "%06d_%s" % (self.pageno + 1, name) - ) + return os.path.join(self.work_folder, "%06d_%s" % (self.pageno + 1, name)) def cleanup_working_files(work_folder, options): @@ -88,7 +114,7 @@ class LogNamePageAdapter(logging.LoggerAdapter): ) -def get_logger(options=None, prefix='ocrmypdf', filename=None, page=None): +def make_logger(options=None, prefix='ocrmypdf', filename=None, page=None): log = logging.getLogger(prefix) if filename and page: adapter = LogNamePageAdapter(log, dict(filename=filename, page=page)) diff --git a/src/ocrmypdf/_sync.py b/src/ocrmypdf/_sync.py index ad79c306..06e600b7 100644 --- a/src/ocrmypdf/_sync.py +++ b/src/ocrmypdf/_sync.py @@ -29,7 +29,7 @@ from tempfile import mkdtemp from tqdm import tqdm from . import VERSION -from ._jobcontext import PDFContext, cleanup_working_files, get_logger +from ._jobcontext import PDFContext, cleanup_working_files, make_logger from ._pipeline import ( convert_to_pdfa, copy_final, @@ -83,17 +83,13 @@ def exec_page_sync(page_context): if is_ocr_required(page_context): if options.rotate_pages: # Rasterize - rasterize_preview_out = rasterize_preview( - page_context.pdf_context.origin, page_context - ) + rasterize_preview_out = rasterize_preview(page_context.origin, page_context) orientation_correction = get_orientation_correction( rasterize_preview_out, page_context ) rasterize_out = rasterize( - page_context.pdf_context.origin, - page_context, - correction=orientation_correction, + page_context.origin, page_context, correction=orientation_correction ) preprocess_out = rasterize_out @@ -240,7 +236,7 @@ def exec_concurrent(context): def run_pipeline(options): - log = get_logger(options, __name__) + log = make_logger(options, __name__) log.debug('ocrmypdf ' + VERSION) result = check_options(options)