| 96 | |
| 97 | |
| 98 | def _fork( |
| 99 | path, |
| 100 | pages, |
| 101 | pagefn, |
| 102 | pagefn_args, |
| 103 | pagefn_kwargs, |
| 104 | initfn, |
| 105 | initfn_args, |
| 106 | initfn_kwargs, |
| 107 | concurrency, |
| 108 | stats, |
| 109 | ): |
| 110 | verbose = 0 |
| 111 | if concurrency is None: |
| 112 | concurrency = multiprocessing.cpu_count() |
| 113 | # We write page numbers to `queue_down` and read `(page_num, text)` from |
| 114 | # `queue_up`. Workers each repeatedly read the next available page number |
| 115 | # from `queue_down`, extract the text and write it onto `queue_up`. |
| 116 | # |
| 117 | # This is better than pre-allocating a subset of pages to each worker |
| 118 | # because it ensures there will never be idle workers until we are near the |
| 119 | # end with fewer pages left than workers. |
| 120 | # |
| 121 | queue_down = multiprocessing.Queue() |
| 122 | queue_up = multiprocessing.Queue() |
| 123 | def childfn(): |
| 124 | document = None |
| 125 | if verbose: |
| 126 | pymupdf.log(f'{os.getpid()=}: {initfn=} {initfn_args=}') |
| 127 | _worker_init( |
| 128 | path, |
| 129 | initfn, |
| 130 | initfn_args, |
| 131 | initfn_kwargs, |
| 132 | pagefn, |
| 133 | pagefn_args, |
| 134 | pagefn_kwargs, |
| 135 | stats, |
| 136 | ) |
| 137 | while 1: |
| 138 | if verbose: |
| 139 | pymupdf.log(f'{os.getpid()=}: calling get().') |
| 140 | page_num = queue_down.get() |
| 141 | if verbose: |
| 142 | pymupdf.log(f'{os.getpid()=}: {page_num=}.') |
| 143 | if page_num is None: |
| 144 | break |
| 145 | try: |
| 146 | if not document: |
| 147 | if stats: |
| 148 | t = time.time() |
| 149 | document = pymupdf.Document(path) # pylint: disable=c-extension-no-member |
| 150 | if stats: |
| 151 | _stats_write(t, 'pymupdf.Document(path)') |
| 152 | |
| 153 | if stats: |
| 154 | t = time.time() |
| 155 | page = document[page_num] |