Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ You can contribute to `pypdf on GitHub <https://github.com/py-pdf/pypdf>`_.
user/file-size
user/pdf-version-support
user/pdfa-compliance
user/logging


.. toctree::
Expand Down
110 changes: 110 additions & 0 deletions docs/user/logging.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# Logging

All log messages from `pypdf` go through Python’s standard `logging` library under the logger name `pypdf`. This gives you full control over verbosity, whether you want detailed debug information or only critical errors.

## Filtering logs

You can adjust the minimum log level of pypdf as follow:

```py
import logging
from pypdf import PdfReader

# Get the logger for the pypdf library
# This allows you to configure its logging level independently
logger = logging.getLogger("pypdf")
logger.setLevel(logging.ERROR)

reader = PdfReader("file.pdf")
```

## Temporarily Reducing Log Noise

If you only want to suppress logs during a specific operation, you can wrap that code in a context manager:

```py
import logging
from contextlib import contextmanager


@contextmanager
def reduce_log_level(level=logging.ERROR):
logger = logging.getLogger("pypdf")
old_level = logger.level
logger.setLevel(level)
try:
yield
finally:
logger.setLevel(old_level)
```

#### Usage:

```py
from pypdf import PdfReader, PdfWriter
from my_module import reduce_log_level # Adjust path to your module

# Standard logging level applies
reader = PdfReader("file.pdf")
writer = PdfWriter()

page = reader.pages[0]
writer.add_page(page)

with reduce_log_level(level=logging.ERROR):
# Adjusted level applies
# Logs lower than ERROR will be filtered-out
do_something()

# Original logging level applies
with open("new_file.pdf", "wb") as fp:
writer.write(fp)
```

## Customizing Log Records

If you prefer to remap log levels (e.g., turn errors into warnings), you can subclass `logging.Logger` as follow:

```py
import logging
from pypdf import PdfReader

class PypdfCustomLogger(logging.Logger):
def makeRecord(self, name: str, level: int, *args, **kwargs):
if name == "pypdf":
level_mapping = {
logging.NOTSET: logging.NOTSET,
logging.DEBUG: logging.DEBUG,
logging.INFO: logging.DEBUG,
logging.WARNING: logging.INFO,
logging.ERROR: logging.WARNING,
logging.CRITICAL: logging.ERROR,
}
new_level = level_mapping.get(level, logging.DEBUG)
else:
new_level = level

# Generate a record using the new level defined
return super().makeRecord(name, new_level, *args, **kwargs)
```

#### Usage:

```py
import logging
from my_module import PypdfCustomLogger # Adjust path to your module

logging.setLoggerClass(PypdfCustomLogger)
logging.basicConfig()

pdf_logger = logging.getLogger("pypdf")
other_logger = logging.getLogger("other_logger")

# pypdf logger level is adjusted
pdf_logger.info("This will be captured as a DEBUG message.")
pdf_logger.warning("This will be captured as a INFO message.")
pdf_logger.error("This will be captured as a WARNING message.")

# Other loggers are not impacted
other_logger.error("This will be captured as a ERROR message.")
```