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

Python包内globals()失效:如何让函数将对象加入全局工作区?

问题原因

当source_lines函数放入包模块后,函数内部调用的globals()返回的是包模块自身的全局命名空间,而非调用该函数的脚本/交互式环境的全局命名空间。因此exec执行的代码会将对象注入到包模块的globals中,调用者的全局空间自然无法访问这些对象。

解决方案

要实现将对象注入到调用者的全局空间,需要获取调用者的globals,而非函数所在模块的globals。可以通过inspect模块获取调用栈的上一层上下文,直接拿到调用者的全局命名空间。

修改后的函数代码

from re import search
import tempfile
import os
import inspect

def source_lines(path: str, start_line: str, end_line: str):
    # 获取调用者的全局命名空间
    caller_globals = inspect.stack()[1].frame.f_globals

    with open(path, "r") as f:
        script = f.readlines()

    starts = [i for i, line in enumerate(script) if search(start_line, line)]
    ends = [i for i, line in enumerate(script) if search(end_line, line)]

    out = []
    for s, e in zip(starts, ends):
        out.append(script[s:e])

    out_flat = [item for sublist in out for item in sublist]

    with tempfile.TemporaryDirectory() as td:
        f_name = os.path.join(td, 'tempsource.py')
        with open(f_name, 'w+t') as fh:
            fh.write('\n'.join(out_flat))
            fh.seek(0)
            # 用调用者的globals执行代码
            exec(open(f_name).read(), caller_globals)

关键改动说明

  • 引入inspect模块,通过inspect.stack()[1].frame.f_globals获取调用者的全局命名空间:inspect.stack()返回调用栈列表,索引1对应调用source_lines的上下文层级,从中取出frame的f_globals就是调用者的全局字典。
  • 将exec的第二个参数从globals()替换为caller_globals,确保执行的代码将对象注入到调用者的全局空间。

备选方案:手动传入globals

如果不想依赖inspect模块,可以让函数接收一个globals_dict参数,由用户调用时主动传入自身的globals():

def source_lines(path: str, start_line: str, end_line: str, globals_dict=None):
    # 若未传参,默认使用调用者的globals(需用户手动传入才生效)
    if globals_dict is None:
        raise ValueError("请传入调用者的globals()作为globals_dict参数")
    # ... 其余逻辑不变 ...
    exec(open(f_name).read(), globals_dict)

# 用户调用示例
source_lines(
    path='delete_me.py',
    start_line='^## (Dependencies|Main fun)',
    end_line='^#\s*$',
    globals_dict=globals()
)

这种方式需要用户主动传参,自动化程度不如inspect方案,但避免了对inspect模块的依赖。

注意事项
  • inspect.stack()在性能敏感场景下存在轻微开销,但完全适配交互式开发的使用场景。
  • 你提到exec存在代码异味,这一观点是合理的:动态执行代码会降低代码可维护性与安全性,建议仅在交互式开发的特定场景下使用,生产环境尽量避免此类实现。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 04:37:45