Install & Compatibility
Where this runs
tested against v0.5.0 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslpy 3.10–3.920 runs
installs and imports cleanly · install 0.0s · import 0.039s · 18.2MB
glibcpy 3.10–3.920 runs
installs and imports cleanly · install 1.6s · import 0.038s · 19MB
16MB installed
● package 16MB
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
PdfReader
✓ from pdfrw import PdfReader
✗ from pdfrw2 import PdfReader
The installed package is `pdfrw2`, but the main module to import from is named `pdfrw` for backward compatibility with the original library.
PdfWriter
✓ from pdfrw import PdfWriter
✗ from pdfrw2 import PdfWriter
The installed package is `pdfrw2`, but the main module to import from is named `pdfrw` for backward compatibility with the original library.
PageMerge
✓ from pdfrw import PageMerge
This quickstart demonstrates how to read an existing PDF file and write its contents to a new PDF file using pdfrw2. It shows the basic usage of `PdfReader` and `PdfWriter` to copy a PDF. For a more robust example with actual PDF content, you would typically start with a real PDF file.
import os
from pdfrw import PdfReader, PdfWriter
# Create dummy PDF files for demonstration if they don't exist
# In a real scenario, you would have existing PDF files.
# This example just copies a (potentially empty) file to simulate input.
# For a true example, you'd need a PDF generator or existing files.
def create_dummy_pdf(filename):
# This is a highly simplified 'creation' for demonstration purposes.
# In a real app, you'd use a library like reportlab or have actual PDFs.
with open(filename, 'w') as f:
f.write('%PDF-1.4\n1 0 obj <</Type/Catalog/Pages 2 0 R>> endobj\n2 0 obj <</Type/Pages/Count 0>> endobj\nxref\n0 3\n0000000000 65535 f\n0000000009 00000 n\n0000000052 00000 n\ntrailer<</Size 3/Root 1 0 R>>startxref\n106\n%%EOF')
input_pdf_path = 'input.pdf'
output_pdf_path = 'output.pdf'
if not os.path.exists(input_pdf_path):
print(f"Creating dummy {input_pdf_path} for quickstart...")
create_dummy_pdf(input_pdf_path)
try:
# Read an existing PDF
trailer = PdfReader(input_pdf_path)
# Create a new PDF writer
writer = PdfWriter()
# Add all pages from the input PDF to the writer
writer.addpages(trailer.pages)
# Write the combined PDF to a new file
writer.write(output_pdf_path)
print(f"Successfully copied '{input_pdf_path}' to '{output_pdf_path}'")
except Exception as e:
print(f"An error occurred: {e}")
finally:
# Clean up dummy files
# os.remove(input_pdf_path) # Uncomment to remove after running
# os.remove(output_pdf_path) # Uncomment to remove after running
pass
Debug
Known issues
gotchaThe PyPI package name is `pdfrw2`, but the Python module to import is `pdfrw`. Attempting to `import pdfrw2` will result in a `ModuleNotFoundError`.fixAlways use `from pdfrw import ...` for imports.
affects: All pdfrw2 versions (0.1.0+)
gotchaHandling encrypted PDF files requires the optional `pycryptodome` package. Without it, attempts to open or process encrypted PDFs will fail with an error indicating missing encryption support.fixInstall the dependency: `pip install pdfrw2[crypto]` (or `pip install pycryptodome` separately if your shell expands square brackets).
affects: All pdfrw2 versions (0.1.0+)
gotchaIf migrating code from very old versions of `pdfrw` (the unmaintained predecessor), you might encounter `ImportError` related to `collections` vs. `collections.abc` for abstract base classes. `pdfrw2` has addressed this, but ensure your Python environment is compatible.fixEnsure you are using `pdfrw2` (which incorporates the fix) and a Python version 3.6+. If you see such an error in `pdfrw2` code, report it to the maintainers; it indicates a regression.
affects: Potentially an issue when migrating from pdfrw < 0.4.2 to pdfrw2
Errors
Common errors & fixes
ModuleNotFoundError: No module named 'pdfrw2'
Attempting to import the package using its PyPI name `pdfrw2` instead of its module name `pdfrw`.
fixChange your import statements from `import pdfrw2` to `import pdfrw`, or `from pdfrw2 import ...` to `from pdfrw import ...`.
AttributeError: 'NoneType' object has no attribute 'encrypt'
Trying to open or manipulate an encrypted PDF without the `pycryptodome` library installed. `pdfrw2` dynamically loads encryption support.
fixInstall the optional dependency for encryption: `pip install pycryptodome`.
File "/path/to/pdfrw/pdfreader.py", line XYZ, in __init__
raise PdfParseError('File has no pages?')
The PDF file being read is either empty, corrupted, or not a valid PDF document that pdfrw2 can parse.
fixEnsure the input file is a valid, well-formed PDF. Check the file's integrity and content. Try opening it with a standard PDF viewer.
Upgrade
Version history
0.5.0latest on PyPI · released Nov 30, 2021
Audit
Dependencies
pycryptodomeoptionalRequired for handling encrypted PDF files.