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

如何在mylibrary内部区分import mylibrary与from mylibrary import abc两种导入方式?

区分两种导入方式的解决方案

针对你的需求——区分import mylibrary(供othertool使用,需执行专属初始化)和from mylibrary import abc(常规使用,不执行初始化),这里提供几种可行的方案,按可靠性和实用性排序:

方案1:通过环境变量标记(最可靠)

如果能控制othertool的启动方式,或者可以协调othertool开发者添加环境变量,这是最稳定的方案:

在othertool启动时设置专属环境变量(比如MYLIBRARY_RUN_FOR_OTHERTOOL=1),然后在你的mylibrary/__init__.py中检查这个变量:

import os

# 检查是否来自othertool的调用
if os.environ.get("MYLIBRARY_RUN_FOR_OTHERTOOL") == "1":
    # 执行othertool专属初始化代码
    from . import main_othertool
    # 这里可以添加更多初始化逻辑,比如配置环境、加载资源等

优点:完全不受工具名称变化影响,逻辑简单且可靠,没有额外依赖。
缺点:需要协调othertool的运行配置或开发者支持。

方案2:通过调用栈上下文判断导入类型

如果无法修改othertool的配置,可以通过分析调用栈的源代码,判断当前是哪种导入方式:

import inspect

def is_direct_import():
    """判断当前是否是直接import mylibrary的场景"""
    try:
        # 获取调用当前模块的栈帧
        caller_frame = inspect.currentframe().f_back
        if not caller_frame:
            return False
        
        # 获取调用者的源代码行
        source_lines, start_line = inspect.getsourcelines(caller_frame.f_code)
        line_idx = caller_frame.f_lineno - start_line
        if line_idx < 0 or line_idx >= len(source_lines):
            return False
        
        current_line = source_lines[line_idx].strip()
        # 判断是否是直接import语句
        return current_line.startswith("import mylibrary")
    except (OSError, IndexError):
        # 无法读取源代码时(比如pyc文件、交互式环境),默认返回False
        return False

# 根据判断结果执行初始化
if is_direct_import():
    from . import main_othertool

优点:无需修改othertool,纯Python实现。
缺点:如果调用者的代码是编译后的(如pyc)、压缩的,或者导入语句被拆分多行,可能判断失效。

方案3:通过父进程名称判断(需第三方依赖)

如果允许引入第三方库,可以用psutil检查父进程的名称,替代之前的sys.argv判断:

首先安装psutil:

pip install psutil

然后在__init__.py中:

import psutil

def is_othertool_process():
    """判断父进程是否是othertool"""
    try:
        parent_process = psutil.Process().parent()
        parent_name = parent_process.name()
        # 匹配可能的工具名称(可以扩展列表)
        return parent_name in ["othertool", "othertool.py", "othertool.exe"]
    except (psutil.NoSuchProcess, psutil.AccessDenied):
        return False

if is_othertool_process():
    from . import main_othertool

优点:比sys.argv更可靠,不受命令行参数中工具名称的位置影响。
缺点:需要依赖第三方库,且如果父进程名称被修改,仍需更新代码。

方案4:延迟初始化(适配工具调用逻辑)

如果othertool在import mylibrary后会调用特定的函数(比如mylibrary.main_othertool),可以将初始化逻辑延迟到该函数被调用时执行:

# mylibrary/__init__.py
_initialized = False

def main_othertool():
    global _initialized
    if not _initialized:
        # 执行初始化代码
        print("Running othertool initialization...")
        _initialized = True
    # 原有main_othertool的逻辑
    ...

优点:无需区分导入方式,只有当工具实际使用专属功能时才初始化,避免不必要的开销。
缺点:如果othertool依赖导入时就完成初始化(比如某些全局配置),这个方案不适用。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 10:32:30