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

Python:猴子补丁修复缺失导入失效问题排查

猴子补丁修复缺失导入后原方法仍无法获取导入的问题

问题背景

MyClass是gdb.Command的子类,尝试通过猴子补丁给mymodule.MyClass.invoke方法补加getopt导入,但原方法old_invoke()执行时依然抛出NameError,提示找不到getopt。

操作步骤及报错

(gdb) pi
>>> import mymodule
>>> old_invoke = mymodule.MyClass.invoke
>>> def new_invoke(self, *k, **kw):
...   print("New invoke")
...   import getopt
...   old_invoke(self, *k, **kw)
...
>>> mymodule.MyClass.invoke = new_invoke
>>>
(gdb) my_gdb_command
New invoke
Python Exception <class 'NameError'> name 'getopt' is not defined:
Error occurred in Python: name 'getopt' is not defined

相关文件及加载方式

mymodule.py

import gdb
class MyClass(gdb.Command):
   ...

   def invoke(self, arg, from_tty):
      options, remainder = getopt.getopt(args, 'p:s:t:o:')
      ...

MyClass()

myothermodule.py

import mymodule
...

加载命令

(gdb) source myothermodule.py

问题原因

Python函数的作用域是定义时确定的,原invoke方法在mymodule模块中定义,该模块未导入getopt。即使在猴子补丁的new_invoke中导入getopt,也只是在new_invoke的局部作用域或当前交互环境中生效,无法进入原invoke方法所在的模块命名空间,因此原方法找不到getopt。

解决方法

方法1:将getopt导入到mymodule的命名空间

直接把getopt添加到mymodule模块的全局命名空间中,让原invoke方法能在自己的模块环境中找到它:

(gdb) pi
>>> import mymodule
>>> import getopt
>>> mymodule.getopt = getopt
>>> old_invoke = mymodule.MyClass.invoke
>>> def new_invoke(self, *k, **kw):
...   print("New invoke")
...   old_invoke(self, *k, **kw)
...
>>> mymodule.MyClass.invoke = new_invoke

方法2:修改原invoke方法的全局字典

直接修改原invoke方法的__globals__属性,把getopt注入到它定义时的全局环境:

(gdb) pi
>>> import mymodule
>>> import getopt
>>> old_invoke = mymodule.MyClass.invoke
>>> old_invoke.__globals__['getopt'] = getopt
>>> def new_invoke(self, *k, **kw):
...   print("New invoke")
...   old_invoke(self, *k, **kw)
...
>>> mymodule.MyClass.invoke = new_invoke

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 01:58:07