Files
ocrmypdf/docs/api.md
T

178 lines
6.1 KiB
Markdown
Raw Normal View History

2025-04-17 15:03:21 -07:00
% SPDX-FileCopyrightText: 2022 James R. Barlow
% SPDX-License-Identifier: CC-BY-SA-4.0
2022-07-28 01:06:46 -07:00
2025-04-17 15:03:21 -07:00
# Using the OCRmyPDF API
2019-05-24 01:05:32 -07:00
2019-06-22 17:29:26 -07:00
OCRmyPDF originated as a command line program and continues to have this
legacy, but parts of it can be imported and used in other Python
applications.
2019-05-24 01:05:32 -07:00
2019-06-22 17:29:26 -07:00
Some applications may want to consider running ocrmypdf from a
subprocess call anyway, as this provides isolation of its activities.
2019-05-24 01:05:32 -07:00
2025-04-17 15:03:21 -07:00
## Example
2019-05-24 01:05:32 -07:00
2021-10-04 09:34:39 +02:00
OCRmyPDF provides one high-level function to run its main engine from an
application.
```{versionchanged} 17.0
The {func}`ocrmypdf.ocr` function now accepts an {class}`~ocrmypdf.OcrOptions`
object as its first argument, providing a cleaner API with full type hints
and validation. The previous positional argument style remains supported.
```
### Modern API (recommended)
The recommended way to call {func}`ocrmypdf.ocr` is to construct an
{class}`~ocrmypdf.OcrOptions` object with all settings, then pass it
as the sole argument:
```python
import ocrmypdf
from ocrmypdf import OcrOptions
if __name__ == '__main__': # To ensure correct behavior on Windows and macOS
options = OcrOptions(
input_file='input.pdf',
output_file='output.pdf',
deskew=True,
languages=['eng'],
)
ocrmypdf.ocr(options)
```
{class}`~ocrmypdf.OcrOptions` is a Pydantic model that provides:
- Full type hints and IDE autocompletion
- Validation of option values at construction time
- Clear documentation of all available options
```{versionadded} 17.0
The {class}`~ocrmypdf.OcrOptions` class is now exported from the top-level
`ocrmypdf` module.
```
### Legacy API
For compatibility with OCRmyPDF < v17, the traditional calling style
with positional arguments is still fully supported:
2019-05-24 01:05:32 -07:00
2025-04-17 15:03:21 -07:00
```python
import ocrmypdf
2019-05-24 01:05:32 -07:00
2025-04-17 15:03:21 -07:00
if __name__ == '__main__': # To ensure correct behavior on Windows and macOS
ocrmypdf.ocr('input.pdf', 'output.pdf', deskew=True)
```
2019-05-24 01:05:32 -07:00
With this style, all of the command line arguments are available
2019-06-22 17:29:26 -07:00
and may be passed as equivalent keywords.
2019-05-24 01:05:32 -07:00
2025-04-17 15:03:21 -07:00
A few differences are that `verbose` and `quiet` are not available.
2019-06-22 17:29:26 -07:00
Instead, output should be managed by configuring logging.
2019-05-24 01:05:32 -07:00
2025-04-17 15:03:21 -07:00
### Parent process requirements
2019-05-24 01:05:32 -07:00
2025-04-17 15:03:21 -07:00
The {func}`ocrmypdf.ocr` function runs OCRmyPDF similar to command line
2019-07-27 04:04:33 -07:00
execution. To do this, it will:
2023-09-30 17:05:58 -07:00
- create worker processes or threads
2020-11-03 17:09:58 -08:00
- manage the signal flags of its worker processes
2019-07-27 04:04:33 -07:00
- execute other subprocesses (forking and executing other programs)
2019-05-24 01:05:32 -07:00
2025-04-17 15:03:21 -07:00
The Python process that calls {func}`ocrmypdf.ocr()` must be sufficiently
2020-11-27 13:54:36 -08:00
privileged to perform these actions.
2019-05-24 01:05:32 -07:00
2021-07-05 23:12:51 +02:00
There currently is no option to manage how jobs are scheduled other
2025-04-17 15:03:21 -07:00
than the argument `jobs=` which will limit the number of worker
2019-06-22 17:29:26 -07:00
processes.
2019-05-24 01:05:32 -07:00
2025-04-17 15:03:21 -07:00
Creating a child process to call {func}`ocrmypdf.ocr()` is suggested. That
2019-06-22 17:29:26 -07:00
way your application will survive and remain interactive even if
2023-09-30 17:05:58 -07:00
OCRmyPDF fails for any reason. For example:
2025-04-17 15:03:21 -07:00
```python
from multiprocessing import Process
import ocrmypdf
from ocrmypdf import OcrOptions
2023-09-30 17:05:58 -07:00
2025-04-17 15:03:21 -07:00
def ocrmypdf_process():
options = OcrOptions(input_file='input.pdf', output_file='output.pdf')
ocrmypdf.ocr(options)
2023-09-30 17:05:58 -07:00
2025-04-17 15:03:21 -07:00
def call_ocrmypdf_from_my_app():
p = Process(target=ocrmypdf_process)
p.start()
p.join()
```
2019-05-24 01:05:32 -07:00
2025-04-17 15:03:21 -07:00
Programs that call {func}`ocrmypdf.ocr()` should also install a SIGBUS signal
2020-08-03 16:03:54 -07:00
handler (except on Windows), to raise an exception if access to a memory
mapped file fails. OCRmyPDF may use memory mapping.
2025-04-17 15:03:21 -07:00
{func}`ocrmypdf.ocr()` will take a threading lock to prevent multiple runs of itself
2021-01-01 01:37:09 -08:00
in the same Python interpreter process. This is not thread-safe, because of how
OCRmyPDF's plugins and Python's library import system work. If you need to parallelize
OCRmyPDF, use processes.
2025-04-17 15:03:21 -07:00
:::{warning}
On Windows and macOS, the script that calls {func}`ocrmypdf.ocr()` must be
protected by an "ifmain" guard (`if __name__ == '__main__'`). If you do
not take at least one of these steps, process semantics will prevent
OCRmyPDF from working correctly.
:::
2025-04-17 15:03:21 -07:00
### Logging
2019-05-24 01:05:32 -07:00
2025-04-17 15:03:21 -07:00
OCRmyPDF will log under loggers named `ocrmypdf`. In addition, it
imports `pdfminer` and `PIL`, both of which post log messages under
2019-06-22 17:29:26 -07:00
those logging namespaces.
2019-05-24 01:05:32 -07:00
2019-06-22 17:29:26 -07:00
You can configure the logging as desired for your application or call
2025-04-17 15:03:21 -07:00
{func}`ocrmypdf.configure_logging` to configure logging the same way
OCRmyPDF itself does. The command line parameters such as `--quiet`
and `--verbose` have no equivalents in the API; you must use the
2019-06-22 17:29:26 -07:00
provided configuration function or do configuration in a way that suits
your use case.
2019-05-24 01:05:32 -07:00
2025-04-17 15:03:21 -07:00
### Progress monitoring
2019-05-24 01:05:32 -07:00
2025-04-17 15:03:21 -07:00
OCRmyPDF uses the `rich` package to implement its progress bars.
{func}`ocrmypdf.configure_logging` will set up logging output to
`sys.stderr` in a way that is compatible with the display of the
progress bar. Use `ocrmypdf.ocr(...progress_bar=False)` to disable
2019-11-08 02:59:02 -08:00
the progress bar.
2019-05-24 01:05:32 -07:00
2025-04-17 15:03:21 -07:00
### Standard output
2023-09-30 17:05:58 -07:00
OCRmyPDF is strict about not writing to standard output so that
users can safely use it in a pipeline and produce a valid output
file. A caller application will have to ensure it does not write to
standard output either, if it wants to be compatible with this
2023-10-31 00:12:15 -07:00
behavior and support piping to a file. Another benefit of running
OCRmyPDF in a child process, as recommended above, is that it will
not interfere with the parent process's standard output.
2023-09-30 17:05:58 -07:00
2025-04-17 15:03:21 -07:00
### Exceptions
2019-05-24 01:05:32 -07:00
2025-04-17 15:03:21 -07:00
OCRmyPDF may throw standard Python exceptions, `ocrmypdf.exceptions.*`
2019-06-22 17:29:26 -07:00
exceptions, some exceptions related to multiprocessing, and
2025-04-17 15:03:21 -07:00
{exc}`KeyboardInterrupt`. The parent process should provide an exception
2019-06-22 17:29:26 -07:00
handler. OCRmyPDF will clean up its temporary files and worker processes
automatically when an exception occurs.
2019-05-24 01:05:32 -07:00
2019-06-20 02:45:14 -07:00
When OCRmyPDF succeeds conditionally, it returns an integer exit code.
### Plugin Development Changes
```{versionchanged} 16.13
Plugin hooks now receive {class}`~ocrmypdf.OcrOptions` objects instead of
`argparse.Namespace`.
```
- {class}`~ocrmypdf.OcrOptions` provides the same attribute access as `Namespace` (duck-typing compatible)
- Plugin developers should update type hints: `from ocrmypdf import OcrOptions`
- Built-in plugins no longer modify options in-place for better immutability
Most existing plugins will continue working without modification due to the
duck-typing compatibility between {class}`~ocrmypdf.OcrOptions` and `Namespace`.