Python:使用猴子补丁修复缺失的导入

huangapple go评论55阅读模式
英文:

Python: Fix missing import with a monkey patch

问题

以下是您要翻译的内容:

我正在尝试对丢失的导入进行猴子补丁。旧的invoke() 仍然没有导入。

如果相关的话,MyClass 是一个 gdb.Command

(gdb) pi
>>> import mymodule
>>> old_invoke = mymodule.MyClass.invoke
>>> def new_invoke(self, *k, **kw):
...   print("新的调用")
...   import getopt
...   old_invoke(self, *k, **kw)
...
>>> mymodule.MyClass.invoke = new_invoke
>>>
(gdb) my_gdb_command
新的调用
Python 异常 <class 'NameError'>:名称 'getopt' 未定义:
Python 中发生错误名称 'getopt' 未定义

另外,如果相关的话,初始文件和源代码看起来类似于这样:

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
英文:

I am trying to monkey patch a missing import. The old_invoke() still does not get the import.
In case it is relevant, MyClass is a gdb.Command.

(gdb) pi
&gt;&gt;&gt; import mymodule
&gt;&gt;&gt; old_invoke = mymodule.MyClass.invoke
&gt;&gt;&gt; def new_invoke(self, *k, **kw):
...   print(&quot;New invoke&quot;)
...   import getopt
...   old_invoke(self, *k, **kw)
...
&gt;&gt;&gt; mymodule.MyClass.invoke = new_invoke
&gt;&gt;&gt;
(gdb) my_gdb_command
New invoke
Python Exception &lt;class &#39;NameError&#39;&gt; name &#39;getopt&#39; is not defined:
Error occurred in Python: name &#39;getopt&#39; is not defined

Also, in case it is relevant, the initial files and sourcing looks something like this:

mymodule.py:

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

   def invoke(self, arg, from_tty):
      options, remainder = getopt.getopt(args, &#39;p:s:t:o:&#39;)
      ...

MyClass()

myothermodule.py:

import mymodule
...

Sourcing the above

(gdb) source myothermodule.py

</details>


# 答案1
**得分**: 2

`old_invoke`试图引用`mymodule`的`getopt`,但该模块不存在。你需要:

```python
&gt;&gt;&gt; import mymodule
&gt;&gt;&gt; old_invoke = mymodule.MyClass.invoke
&gt;&gt;&gt; def new_invoke(self, *k, **kw):
...   print("新调用")
...   import getopt
...   
...   # 这里
...   mymodule.getopt = getopt
...   
...   old_invoke(self, *k, **kw)
...
&gt;&gt;&gt; mymodule.MyClass.invoke = new_invoke

但实际上,你应该在mymodule中只有一个import getopt

# mymodule.py
import getopt
...

然后你的函数就是:

&gt;&gt;&gt; import mymodule
&gt;&gt;&gt; old_invoke = mymodule.MyClass.invoke
&gt;&gt;&gt; def new_invoke(self, *k, **kw):
...   print("新调用")
...   old_invoke(self, *k, **kw)
...
&gt;&gt;&gt; mymodule.MyClass.invoke = new_invoke

附录

另外需要注意的是,在函数中使用import通常不建议。除非你只调用这个函数一次(即使是那样,为什么要这样做?),每次调用函数时都会尝试加载一个模块,最好的情况下将始终对sys.modules进行检查,而你可能不需要这样做。

import getopt放在脚本顶部:

import getopt
import mymodule

mymodule.getopt = getopt

这就是你可能希望它在脚本中的位置。

英文:

old_invoke is trying to reference mymodule's getopt, which doesn't exist. You need:

&gt;&gt;&gt; import mymodule
&gt;&gt;&gt; old_invoke = mymodule.MyClass.invoke
&gt;&gt;&gt; def new_invoke(self, *k, **kw):
...   print(&quot;New invoke&quot;)
...   import getopt
...   
...   # here
...   mymodule.getopt = getopt
...   
...   old_invoke(self, *k, **kw)
...
&gt;&gt;&gt; mymodule.MyClass.invoke = new_invoke

But, realistically, you should just have an import getopt in mymodule:

# mymodule.py
import getopt
...

Then your function is simply:

&gt;&gt;&gt; import mymodule
&gt;&gt;&gt; old_invoke = mymodule.MyClass.invoke
&gt;&gt;&gt; def new_invoke(self, *k, **kw):
...   print(&quot;New invoke&quot;)
...   old_invoke(self, *k, **kw)
...
&gt;&gt;&gt; mymodule.MyClass.invoke = new_invoke

Addendum

As another note, using import in a function isn't generally recommended. Unless you are only calling this function once (and even then, why?), every time you call the function you are attempting to load a module, which at best will always do a check against sys.modules when you probably don't have to.

Have the import getopt at the top of the script:

import getopt
import mymodule

mymodule.getopt = getopt

Which is where you'd probably expect this to be anyways

huangapple
  • 本文由 发表于 2023年6月2日 02:24:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/76384705.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定