You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在导入的Python库内部设置调用脚本的__package__属性

你可以通过inspect模块获取调用方对应的模块对象,直接修改其__package__属性即可,完整的relative_import库实现代码如下:

import inspect
import pathlib
import imptools
import sys

def enable():
    # 跳过当前库的栈帧,获取调用enable()的脚本栈帧
    for frame_info in inspect.stack():
        if frame_info.filename == __file__:
            continue
        caller_frame = frame_info.frame
        break

    # 获取调用脚本对应的模块对象
    caller_module = inspect.getmodule(caller_frame)

    # 仅处理直接作为主脚本运行、且__package__未设置的场景
    if caller_module.__name__ == "__main__" and caller_module.__package__ is None:
        script_path = pathlib.Path(caller_frame.f_globals["__file__"])
        # 计算包名,多层包结构可自行调整为递归查找__init__.py生成完整包名
        package_name = script_path.parent.name
        # 直接修改调用方模块的__package__属性,效果等价于在脚本中直接赋值
        caller_module.__package__ = package_name
        # 执行原有包导入逻辑
        imptools.import_from_path(package_name, "..")
        # 可选:将顶层包路径加入sys.path,确保相对导入可以找到上层模块
        sys.path.insert(0, str(script_path.parent.parent.resolve()))

原理解释

Python中所有运行的模块都是模块类的实例对象,脚本作为主程序运行时对应的是__main__模块。你通过inspect.getmodule()拿到的调用方模块对象,和脚本自身运行时的上下文是同一个对象,直接修改其__package__属性,和在脚本代码里手动写__package__ = "xxx"的效果完全一致。

注意事项

如果你的脚本处于多层嵌套的包结构下(例如parent/child/grandson/script.py),需要调整包名计算逻辑,递归查找父目录下的__init__.py文件,生成完整的点分格式包名(例如parent.child.grandson),才能支持跨多层的相对导入。

内容的提问来源于stack exchange,提问作者danijar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 23:15:02