datawhalechina/hello-agents · error · IOError

无法读取 PDF 文件:{e}

Error message

无法读取 PDF 文件:{e}

What it means

IOError (OSError alias) raised by the paper analyzer when reading a PDF with PyPDF2 fails. The try block covers both file opening and text extraction, so the cause may be a missing/corrupt file, a permissions problem, or a PyPDF2 extraction failure (encrypted PDF, malformed xref, unsupported compression) — all flattened into one message.

Source

Thrown at Co-creation-projects/Yixiang-Wu-LearningAgent/specialist/paper_analyzer.py:81

        """
        # 处理 ~ 路径
        if file_path.startswith("~"):
            file_path = os.path.expanduser(file_path)

        try:
            with open(file_path, "rb") as file:
                reader = PyPDF2.PdfReader(file)
                text = ""

                # 提取前3页的内容(通常包含摘要和引言)
                max_pages = min(3, len(reader.pages))
                for i in range(max_pages):
                    page = reader.pages[i]
                    text += page.extract_text() + "\n"

                return text
        except Exception as e:
            raise IOError(f"无法读取 PDF 文件:{e}")

    def _extract_keywords_from_text(self, text: str) -> List[str]:
        """
        从文本中提取关键词

        Args:
            text: 论文文本

        Returns:
            关键词列表
        """
        # 学术领域常见关键词
        academic_keywords = [
            # 深度学习/机器学习
            "Neural Network",
            "Deep Learning",
            "Transformer",
            "Attention",

View on GitHub (pinned to 606a07d341)

Solutions

  1. Verify the path exists and is a real PDF (check %PDF- magic bytes) before parsing
  2. Handle encrypted PDFs explicitly: if reader.is_encrypted, attempt reader.decrypt('') or reject with a clear message
  3. Split the except clauses: OSError for file access, PyPDF2.errors.PdfReadError for parsing, so the message identifies the real cause
  4. Migrate from the deprecated PyPDF2 to pypdf (drop-in successor) for current bug fixes
  5. Re-download the file if truncated (compare Content-Length or re-fetch on parse failure)

Example fix

# before
try:
    with open(file_path, "rb") as file:
        reader = PyPDF2.PdfReader(file)
        ...
except Exception as e:
    raise IOError(f"无法读取 PDF 文件:{e}")

# after
from pypdf import PdfReader
from pypdf.errors import PdfReadError
try:
    with open(file_path, "rb") as file:
        reader = PdfReader(file)
        if reader.is_encrypted and not reader.decrypt(""):
            raise ValueError("PDF 已加密,无法提取文本")
        ...
except OSError as e:
    raise IOError(f"无法打开 PDF 文件 {file_path}: {e}") from e
except PdfReadError as e:
    raise ValueError(f"PDF 已损坏或格式无效: {e}") from e
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path

def looks_like_pdf(path: str | Path) -> bool:
    p = Path(path)
    if not p.is_file() or p.stat().st_size < 100:
        return False
    with p.open('rb') as f:
        return f.read(5).startswith(b'%PDF-')

Try / catch

try:
    text = analyzer.extract_pdf_text(path)
except (IOError, ValueError) as e:
    logger.warning("skipping unreadable PDF %s: %s", path, e)
    text = ''  # degrade to keyword-only analysis without the paper

Prevention

When it happens

Trigger: open(file_path, 'rb') fails: file does not exist, is a directory, or permission denied; PyPDF2.PdfReader raises on an encrypted PDF without a password; severely malformed or truncated PDF raises PdfReadError during page parsing; page.extract_text() failing on unusual encodings; PyPDF2 not installed raising ImportError inside the try.

Common situations: User-uploaded arXiv PDF that is actually an HTML error page saved with .pdf extension; password-protected or DRM-restricted papers; PyPDF2 3.x API differences (PdfReader vs PdfFileReader) after an upgrade; partial download of a large paper.

Related errors


AI-assisted analysis of datawhalechina/hello-agents@606a07d341 (2026-08-14). Data as JSON: /api/errors/3560dd6212cdab08. Report an issue: GitHub.