datawhalechina/hello-agents · error · ImportError

无法导入 {module_name}.{class_name or ''}: {e}

Error message

无法导入 {module_name}.{class_name or ''}: {e}

What it means

ImportError from utils.helpers.safe_import when importlib.import_module raises ImportError (module missing/broken) or getattr raises AttributeError (class/function not exported) — both are re-raised as one uniform ImportError naming module and class. It exists so plugin-style dynamic loads produce consistent, greppable errors.

Source

Thrown at Co-creation-projects/YYHDBL-HelloCodeAgentCli/utils/helpers.py:56

def safe_import(module_name: str, class_name: Optional[str] = None) -> Any:
    """
    安全导入模块或类
    
    Args:
        module_name: 模块名
        class_name: 类名(可选)
        
    Returns:
        导入的模块或类
    """
    try:
        module = importlib.import_module(module_name)
        if class_name:
            return getattr(module, class_name)
        return module
    except (ImportError, AttributeError) as e:
        raise ImportError(f"无法导入 {module_name}.{class_name or ''}: {e}")

def ensure_dir(path: Path) -> Path:
    """确保目录存在"""
    path.mkdir(parents=True, exist_ok=True)
    return path

def get_project_root() -> Path:
    """获取项目根目录"""
    return Path(__file__).parent.parent.parent

def merge_dicts(dict1: Dict, dict2: Dict) -> Dict:
    """深度合并两个字典"""
    result = dict1.copy()
    for key, value in dict2.items():
        if key in result and isinstance(result[key], dict) and isinstance(value, dict):
            result[key] = merge_dicts(result[key], value)
        else:
            result[key] = value

View on GitHub (pinned to 606a07d341)

Solutions

  1. Verify the module is installed/importable: python -c "import <module>".
  2. Check the exact class name spelling and that it is exported at module level (not nested or private).
  3. After a dependency upgrade, grep the package for the renamed symbol and update the string.
  4. If the module is optional, catch the ImportError and degrade gracefully.

Example fix

# before
cls = safe_import('hello_agents.tools.search', 'WebSearch')  # AttributeError path

# after
import hello_agents.tools.search as m
print([n for n in dir(m) if 'earch' in n])  # find real name, e.g. 'WebSearchTool'
cls = safe_import('hello_agents.tools.search', 'WebSearchTool')
Defensive patterns

Strategy: try-catch

Validate before calling

import importlib.util

def module_importable(name: str) -> bool:
    return importlib.util.find_spec(name) is not None

if not module_importable('hello_agents.tools.web_search'):
    disable_plugin('web_search')

Type guard

def symbol_exists(module_name: str, class_name: str) -> bool:
    try:
        mod = importlib.import_module(module_name)
    except ImportError:
        return False
    return hasattr(mod, class_name)

Try / catch

try:
    cls = safe_import(module_name, class_name)
except ImportError as e:
    logger.warning('plugin %s unavailable: %s', module_name, e)
    cls = None  # skip plugin, keep core running

Prevention

When it happens

Trigger: safe_import('hello_agents.tools.web_search', 'WebSearchTool') when the module is not installed or the class name is misspelled; circular imports surfacing as ImportError; package restructure renaming the class so getattr fails.

Common situations: Plugin registries loading tools by string name from config; version upgrades that moved/renamed classes; optional extras not installed so their modules don't exist.

Related errors


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