Handle errors¶
Files go missing and not every file is a valid PDF. ozaru reports these problems with standard Python exceptions:
| Exception | When it happens |
|---|---|
FileNotFoundError |
The path does not exist. |
PermissionError |
You don't have permission to read the file. |
IsADirectoryError |
The path is a folder, not a file. |
NotADirectoryError |
Part of the path is a file used as if it were a folder. |
OSError |
The file could not be read for another reason. |
ValueError |
The file is not a valid PDF, or the path contains a null byte. |
extract_text also raises ValueError for a PDF that needs a password.
Catch them with try and except:
from pathlib import Path
import ozaru
def read_pdf(path):
try:
return ozaru.extract_text(path)
except FileNotFoundError:
print(f"{path}: file not found")
except ValueError:
print(f"{path}: not a readable PDF")
return None
Path("notes.txt").write_text("This is not a PDF.", encoding="utf-8")
read_pdf("missing.pdf")
read_pdf("notes.txt")
text = read_pdf("report.pdf")
print(f"report.pdf: {len(text)} characters")
Output:
Tip
The text of an exception may change between releases. Rely on the exception type, as this example does, and not on the message.
File errors¶
FileNotFoundError, PermissionError, IsADirectoryError and
NotADirectoryError are the same exceptions Python's open() raises. They are all
subclasses of OSError, so one except OSError catches any problem with the file
itself, and error.filename tells you which path failed:
from pathlib import Path
import ozaru
Path("reports").mkdir()
for path in ["missing.pdf", "reports"]:
try:
ozaru.page_count(path)
except OSError as error:
print(f"{type(error).__name__}: {error.filename}")
Output:
Pages that can't be read¶
Sometimes a PDF opens but one of its pages is damaged. ozaru doesn't throw away
the whole document for that: extract_text returns the text of every page it
could read, leaves the damaged page empty, and emits an ozaru.PageWarning for it.
The page stays in the result as an empty string, so split("\f") still gives one
item per page and the page numbers don't shift.
Download the damaged report, whose
third page is broken, and catch the warnings with the standard
warnings module:
import warnings
import ozaru
with warnings.catch_warnings(record=True) as caught:
warnings.simplefilter("always", ozaru.PageWarning)
text = ozaru.extract_text("damaged-page.pdf")
for warning in caught:
print(f"Page {warning.message.page} could not be read")
for number, page in enumerate(text.split("\f"), start=1):
print(f"Page {number}: {len(page)} characters")
Output:
Each warning has two attributes:
| Attribute | Type | Description |
|---|---|---|
page |
int |
Number of the page that failed, starting at 1 |
reason |
str |
Why the page could not be read |
If you don't catch them, Python prints the warnings to the terminal and your program keeps running.
Stop at the first damaged page¶
When a partial result is not acceptable, turn the warning into an error. Then
extract_text raises ozaru.PageWarning instead of returning:
import warnings
import ozaru
warnings.simplefilter("error", ozaru.PageWarning)
try:
text = ozaru.extract_text("damaged-page.pdf")
except ozaru.PageWarning as error:
print(f"Stopped: page {error.page} could not be read")
Output:
Next: process a folder.