opendatalab/MinerU · error · AttributeError
module {__name__!r} has no attribute {name!r}
Error message
module {__name__!r} has no attribute {name!r} What it means
AttributeError raised by the module-level __getattr__ in mineru/data/io/__init__.py (PEP 562) for any attribute access that is not one of the eagerly listed names ('IOReader', 'IOWriter', 'HttpReader', 'HttpWriter') or the lazily loaded 'S3Reader'/'S3Writer'. The module defers importing the S3 classes to avoid a hard boto3 dependency, so unknown names fall through to this explicit error.
Source
Thrown at mineru/data/io/__init__.py:18
# Copyright (c) Opendatalab. All rights reserved.
from .base import IOReader, IOWriter
from .http import HttpReader, HttpWriter
__all__ = ['IOReader', 'IOWriter', 'HttpReader', 'HttpWriter', 'S3Reader', 'S3Writer']
def __getattr__(name):
"""按需加载 S3 IO 类,避免默认安装场景强制依赖 boto3。"""
if name in {'S3Reader', 'S3Writer'}:
from .s3 import S3Reader, S3Writer
s3_exports = {'S3Reader': S3Reader, 'S3Writer': S3Writer}
globals().update(s3_exports)
return s3_exports[name]
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
View on GitHub (pinned to 4fe4bde114)
Solutions
- Check __all__ in mineru/data/io/__init__.py and import only listed names: IOReader, IOWriter, HttpReader, HttpWriter, S3Reader, S3Writer.
- Fix the typo in the import (e.g. S3Reeder -> S3Reader).
- If importing S3Reader/S3Writer, ensure the [s3] extra is installed since the lazy import of .s3 still needs boto3.
- For renamed/moved classes, grep the package for the new location instead of relying on old paths.
Example fix
# before from mineru.data.io import S3Reeder # AttributeError via __getattr__ # after from mineru.data.io import S3Reader
Defensive patterns
Strategy: type-guard
Validate before calling
import mineru.data.io as mineru_io
ALLOWED = set(mineru_io.__all__)
def safe_getattr(name: str):
if name not in ALLOWED:
raise AttributeError(f'mineru.data.io exports only {sorted(ALLOWED)}, not {name!r}')
return getattr(mineru_io, name) Type guard
def is_mineru_io_export(name: str) -> bool:
import mineru.data.io as m
return name in m.__all__ # ['IOReader','IOWriter','HttpReader','HttpWriter','S3Reader','S3Writer'] Try / catch
try:
from mineru.data.io import S3Reader
except ImportError as e:
raise ImportError(
"expected 'mineru.data.io' exports: "
"IOReader, IOWriter, HttpReader, HttpWriter, S3Reader, S3Writer"
) from e Prevention
- Import only names listed in mineru.data.io.__all__.
- Pin the mineru version so renamed exports don't surprise you on upgrade.
- Let the IDE resolve imports from the installed package, not from memory of an old version.
When it happens
Trigger: `from mineru.data.io import S3Reeder` (typo), `getattr(mineru.data.io, 'FsReader')`, or `hasattr`/dir-driven probing of names removed or never exported from the package.
Common situations: Upgrades where a class was renamed or moved but old import statements remain; IDE autocomplete suggesting a stale name; generic plugin loaders that iterate candidate class names via getattr.
Related errors
- module {__name__!r} has no attribute {name!r}
- S3 reader/writer requires optional dependencies. Install the
- S3 IO requires optional dependencies. Install them with `pip
AI-assisted analysis of opendatalab/MinerU@4fe4bde114 (2026-08-14).
Data as JSON: /api/errors/e925ec2629a88ec5.
Report an issue: GitHub.