pypdfium2 Documentation

repository·main·Indexed 18 days ago

https://github.com/pypdfium2-team/pypdfium2

A Python 3 binding for the PDFium library providing high-performance PDF rendering, inspection, manipulation, and creation. It offers both high-level helpers via the PdfDocument API and direct access to the underlying PDFium C API through a raw ctypes-based interface. Features include text extraction, page rendering to bitmaps, and a command-line interface for document processing.

Tokens
16.4K
Snippets
48
Records
71
Agent score
73%

What's inside pypdfium2

  1. Overview of pypdfium2

    main

    pypdfium2 is an ABI-level Python 3 binding to PDFium, a library used for PDF rendering, inspection, manipulation, and creation. It is built using ctypesgen and utilizes external PDFium binaries. The library provides two ways to interact with PDFium:

    1. Helpers: High-level utilities designed to simplify common PDF tasks.
    2. Raw PDFium API: Direct access to the underlying PDFium C API via ctypes for low-level control.
  2. Understand pypdfium2 licensing

    main

    pypdfium2 is available under Apache-2.0 or BSD-3-Clause licenses. Documentation and examples are licensed under CC-BY-4.0.

    Important Note on PDFium: The underlying PDFium library is available under a BSD-style license. Because pypdfium2 includes PDFium, its license and the licenses of PDFium's dependencies must be shipped with binary distributions.

    Runtime Dependency Note: Some builds may link with the libgcc runtime library. Users should check their specific builds and verify if libgcc's license is compatible with their use case.

  3. Handle pypdfium2 threading and memory limitations

    main

    When using pypdfium2, be aware of the following technical constraints:

    1. Incompatibility with Threading: PDFium is inherently not thread-safe. Do not attempt to use it across multiple threads without proper synchronization or following the specific guidance in the API docs.
    2. Object Lifetime Risks: Python-managed resources must remain available as long as PDFium requires them. Because the Python interpreter can garbage collect objects with a reference count of zero at any time, unreferenced objects required by PDFium might be removed prematurely, leading to non-deterministic memory issues.
    3. No Raw PDF Access: Unlike libraries such as pikepdf, pypdfium2 (via PDFium's public interface) does not provide access to the raw PDF data structure (e.g., reading/writing PDF dictionaries, streams, or name/number trees). It provides abstracted functions instead.
  4. General restrictions and disclaimers for libjpeg-turbo

    main

    When using libjpeg-turbo, adhere to these general rules:

    • No Endorsement: You cannot use the name of the IJG, The libjpeg-turbo Project, or its contributors in advertising, publicity, or to endorse/promote products derived from this software without specific prior written permission.
    • No Warranty: The IJG and The libjpeg-turbo Project do not warrant the software to be free of defects and accept no liability for undesirable consequences resulting from its use.
  5. Handle threading and parallelization in pypdfium2

    main

    PDFium is inherently not thread-safe. You must not call PDFium functions simultaneously across different threads, even if they are operating on different documents. Doing so can crash or corrupt the process.

    To use pypdfium2 in a threaded environment, you must ensure that only a single PDFium call is made at a time (for example, by using a mutex). It is safe to perform PDFium work in one thread while other non-PDFium work occurs in other threads.

    Recommendation: To parallelize expensive tasks like rendering, use processes (e.g., multiprocessing) instead of threads.

  6. Optional runtime dependencies for pypdfium2

    main

    While pypdfium2 has no mandatory runtime dependencies beyond Python and PDFium, several optional packages enable extra features:

    • Pillow (module PIL): Provides convenience adapters to translate between raw bitmap buffers and PIL images. Also used for some CLI image saving functionality.
    • NumPy: Provides helpers to get a NumPy array view of a raw bitmap.
    • opencv-python (module cv2): Can be used in the rendering CLI to save images via the NumPy adapter.
    • tabulate: Enables prettier CLI output for tables.

    Imports for these dependencies are deferred until needed, so there is no startup overhead if they are not installed.

  7. Manage object lifetime when using the Raw API

    main

    When using the raw API, you must manually ensure that Python objects (like buffers or callback functions) remain in memory as long as the underlying C resources (like an FPDF_DOCUMENT) depend on them. If Python garbage collects an object while PDFium is still using it, it will lead to memory corruption or segmentation faults.

    Pattern for custom file access: If using FPDF_LoadCustomDocument, the FPDF_FILEACCESS structure and its associated callback functions must be kept alive until FPDF_CloseDocument is called. A common pattern is to wrap these in a 'Data Holder' class that maintains references to the buffer and the callback function.

    class PdfDataHolder:
        def __init__(self, buffer, function):
            self.buffer = buffer
            self.function = function  # Keeps the callback alive
    
        def close(self):
            id(self.function)  # Ensure function is alive until this point
            self.buffer.close()
    
    # Usage
    data_holder = PdfDataHolder(py_buffer, fileaccess.m_GetBlock)
    pdf = pdfium_c.FPDF_LoadCustomDocument(fileaccess, None)
    
    # ... work with pdf ...
    
    pdfium_c.FPDF_CloseDocument(pdf)
    data_holder.close()
  8. Access the Raw PDFium API via pypdfium2.raw

    main

    For features not yet covered by high-level helpers, you can access the raw PDFium C API through the pypdfium2.raw namespace.

    Key considerations for the Raw API:

    • Positional Arguments Only: Functions do not support keyword arguments.
    • No Default Values: You must provide a value for every argument.
    • Output Parameters: Many functions use ctypes objects (like c_int or c_ulong) as arguments to return values. You must initialize these objects and then access their .value attribute.
    • String Handling: Strings must often be NUL-terminated and encoded (e.g., UTF-8 for FPDF_LoadDocument or UTF-16LE for certain text functions). For output strings, you typically must call the function twice: once to get the required buffer size, and once to fill the pre-allocated buffer.
    • Implicit Resolution: When calling a raw function that takes a handle, you can often pass the high-level helper object directly; pypdfium2 will automatically resolve it to the underlying raw object handle.
    import pypdfium2.raw as pdfium_c
    
    # Implicit resolution: passing a helper object to a raw function
    permission_flags = pdfium_c.FPDF_GetDocPermission(pdf)
    
    # Explicit resolution
    permission_flags = pdfium_c.FPDF_GetDocPermission(pdf.raw)
    
    # Using output parameters
    c_version = ctypes.c_int()
    ok = pdfium_c.FPDF_GetFileVersion(pdf, c_version)
    version = c_version.value if ok else None
  9. Understand the pypdfium2 API layers

    main

    pypdfium2 provides three distinct layers of interaction:

    1. The Raw API (pypdfium2.raw or pypdfium2_raw): A direct mapping to the PDFium C API via ctypes. It is stable and highly compatible but requires manual memory management and is difficult to use.
    2. The Support Model API (pypdfium2): A set of Pythonic helper classes built around the raw API. It is easier and safer to use but is currently in beta and may undergo breaking changes. It covers only a subset of PDFium features.
    3. The Internal API (pypdfium2.internal): Utilities that aid the raw API and are used by helpers, but are not part of the public support model namespace.

    Key Integration Detail: Wrapper objects in the support model provide a .raw attribute to access the underlying ctypes object. Additionally, helpers automatically resolve to their raw counterparts if passed as a C function parameter via a ctypes hook.

  10. Install pypdfium2 with JavaScript/XFA support

    main

    If you require builds with V8 (JavaScript) and XFA support, you must bypass the standard wheels and run the setup manually using the PDFIUM_PLATFORM=auto-v8 environment variable.

    PDFIUM_PLATFORM=auto-v8 pip install -v pypdfium2 --no-binary pypdfium2
  11. Manage memory and object lifecycles in the support model

    main

    In the support model API, PDFium objects must be closed to release allocated memory and file handles.

    Automatic vs. Explicit Closing

    • Automatic: Helper classes implement automatic closing during garbage collection using weakref.finalize.
    • Explicit: You should call the .close() method on objects to release resources immediately rather than waiting for Python's garbage collector.

    Important Safety Rules

    • No Use After Close: Once an object is closed, it must not be accessed. Closing a parent object (like a PDF document) will automatically close all its children (like pages).
    • Avoid Detaching Raw Objects: Do not detach raw objects from their Python wrappers. Accessing a raw object after its wrapper has been closed (via .close() or garbage collection) results in a use-after-free error.
    • Re-closing: Calling .close() on an already closed object is silently ignored.
    # Example pattern for explicit resource management
    doc = pypdfium2.PdfDocument("example.pdf")
    try:
        page = doc[0]
        # ... perform work ...
    finally:
        page.close()
        doc.close()