{"id":8402,"library":"pdfrw2","title":"pdfrw2 - PDF Reader/Writer Library","description":"pdfrw2 is a maintenance fork of the unmaintained pdfrw library, providing a Pythonic way to read, write, and manipulate PDF files. It allows for tasks like merging, splitting, watermarking, and adding annotations to PDFs. The current version is 0.5.0, and it follows an as-needed release cadence for bug fixes and compatibility updates.","status":"active","version":"0.5.0","language":"en","source_language":"en","source_url":"https://github.com/sarnold/pdfrw2","tags":["pdf","document","reader","writer","manipulation","fork"],"install":[{"cmd":"pip install pdfrw2","lang":"bash","label":"Install pdfrw2"}],"dependencies":[{"reason":"Required for handling encrypted PDF files.","package":"pycryptodome","optional":true}],"imports":[{"note":"The installed package is `pdfrw2`, but the main module to import from is named `pdfrw` for backward compatibility with the original library.","wrong":"from pdfrw2 import PdfReader","symbol":"PdfReader","correct":"from pdfrw import PdfReader"},{"note":"The installed package is `pdfrw2`, but the main module to import from is named `pdfrw` for backward compatibility with the original library.","wrong":"from pdfrw2 import PdfWriter","symbol":"PdfWriter","correct":"from pdfrw import PdfWriter"},{"symbol":"PageMerge","correct":"from pdfrw import PageMerge"}],"quickstart":{"code":"import os\nfrom pdfrw import PdfReader, PdfWriter\n\n# Create dummy PDF files for demonstration if they don't exist\n# In a real scenario, you would have existing PDF files.\n# This example just copies a (potentially empty) file to simulate input.\n# For a true example, you'd need a PDF generator or existing files.\n\ndef create_dummy_pdf(filename):\n    # This is a highly simplified 'creation' for demonstration purposes.\n    # In a real app, you'd use a library like reportlab or have actual PDFs.\n    with open(filename, 'w') as f:\n        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')\n\ninput_pdf_path = 'input.pdf'\noutput_pdf_path = 'output.pdf'\n\nif not os.path.exists(input_pdf_path):\n    print(f\"Creating dummy {input_pdf_path} for quickstart...\")\n    create_dummy_pdf(input_pdf_path)\n\ntry:\n    # Read an existing PDF\n    trailer = PdfReader(input_pdf_path)\n\n    # Create a new PDF writer\n    writer = PdfWriter()\n\n    # Add all pages from the input PDF to the writer\n    writer.addpages(trailer.pages)\n\n    # Write the combined PDF to a new file\n    writer.write(output_pdf_path)\n\n    print(f\"Successfully copied '{input_pdf_path}' to '{output_pdf_path}'\")\n\nexcept Exception as e:\n    print(f\"An error occurred: {e}\")\nfinally:\n    # Clean up dummy files\n    # os.remove(input_pdf_path) # Uncomment to remove after running\n    # os.remove(output_pdf_path) # Uncomment to remove after running\n    pass","lang":"python","description":"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."},"warnings":[{"fix":"Always use `from pdfrw import ...` for imports.","message":"The PyPI package name is `pdfrw2`, but the Python module to import is `pdfrw`. Attempting to `import pdfrw2` will result in a `ModuleNotFoundError`.","severity":"gotcha","affected_versions":"All pdfrw2 versions (0.1.0+)"},{"fix":"Install the dependency: `pip install pdfrw2[crypto]` (or `pip install pycryptodome` separately if your shell expands square brackets).","message":"Handling 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.","severity":"gotcha","affected_versions":"All pdfrw2 versions (0.1.0+)"},{"fix":"Ensure 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.","message":"If 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.","severity":"gotcha","affected_versions":"Potentially an issue when migrating from pdfrw < 0.4.2 to pdfrw2"}],"env_vars":null,"last_verified":"2026-04-16T00:00:00.000Z","next_check":"2026-07-15T00:00:00.000Z","problems":[{"fix":"Change your import statements from `import pdfrw2` to `import pdfrw`, or `from pdfrw2 import ...` to `from pdfrw import ...`.","cause":"Attempting to import the package using its PyPI name `pdfrw2` instead of its module name `pdfrw`.","error":"ModuleNotFoundError: No module named 'pdfrw2'"},{"fix":"Install the optional dependency for encryption: `pip install pycryptodome`.","cause":"Trying to open or manipulate an encrypted PDF without the `pycryptodome` library installed. `pdfrw2` dynamically loads encryption support.","error":"AttributeError: 'NoneType' object has no attribute 'encrypt'"},{"fix":"Ensure the input file is a valid, well-formed PDF. Check the file's integrity and content. Try opening it with a standard PDF viewer.","cause":"The PDF file being read is either empty, corrupted, or not a valid PDF document that pdfrw2 can parse.","error":"File \"/path/to/pdfrw/pdfreader.py\", line XYZ, in __init__\n    raise PdfParseError('File has no pages?')"}]}