如何检测导入的python模块的方法签名

发布于 2025-01-14 03:46:27 字数 1453 浏览 3 评论 0原文

我有一个可以加载和运行扩展的 python 应用程序。它看起来像这样:

import importlib, sys

sys.path.append('.')

module = importlib.import_module( 'extension' )
Extension = getattr(module, 'Extension')
instance = Extension()

instance.FunctionCall(arg1='foo')

用户可以通过实现我定义的类来创建自己的可加载扩展。在本例中,它位于 extension.py 中:

class Extension:
    def FunctionCall(self, arg1):
        print(arg1)

目前效果很好,但我想扩展我的接口以将另一个参数传递到 Extension.FunctionCall

instance.FunctionCall(arg1='foo', arg2='bar')

我怎样才能在保持与现有接口的反向兼容性的同时做到这一点?


如果我进行更改,现有用户会发生以下情况:

$ python3 loader.py 
Traceback (most recent call last):
  File "loader.py", line 9, in <module>
    instance.FunctionCall(arg1='foo', arg2='bar')
TypeError: FunctionCall() got an unexpected keyword argument 'arg2'

一种选择是捕获 TypeError,但这是最好的解决方案吗?看起来它可能会因为接口的多次迭代而变得难以维护。

try:
    instance.FunctionCall(arg1='foo', arg2='bar')
except TypeError:
    instance.FunctionCall(arg1='foo')

另一种选择是将“接口版本”定义为扩展的属性,然后在 case 语句中使用它,但简单地检测支持的内容而不是向用户增加开销会更好。

if hasattr(Extension, 'Standard') and callable(getattr(Extension, 'Standard')):
    standard=instance.Standard()
else:
    standard=0

if standard == 0:
    instance.FunctionCall(arg1='foo')
elif standard == 1:
    instance.FunctionCall(arg1='foo', arg2='bar')

I have a python app which can load and run extensions. It looks like this:

import importlib, sys

sys.path.append('.')

module = importlib.import_module( 'extension' )
Extension = getattr(module, 'Extension')
instance = Extension()

instance.FunctionCall(arg1='foo')

The users can create their own loadable extension by implementing a class I defined. In this case, it is in extension.py:

class Extension:
    def FunctionCall(self, arg1):
        print(arg1)

This works great for now, but I would like to extend my interface to pass another argument into Extension.FunctionCall

instance.FunctionCall(arg1='foo', arg2='bar')

How can I do this while maintaining reverse compatibility with the existing interface?


Here's what happens to existing users if I make the change:

$ python3 loader.py 
Traceback (most recent call last):
  File "loader.py", line 9, in <module>
    instance.FunctionCall(arg1='foo', arg2='bar')
TypeError: FunctionCall() got an unexpected keyword argument 'arg2'

One option is to catch the TypeError, but is this the best solution? It looks like it could get unmaintainable with several iterations of interfaces.

try:
    instance.FunctionCall(arg1='foo', arg2='bar')
except TypeError:
    instance.FunctionCall(arg1='foo')

Another option is to define the "interface version" as a property of the extension and then use that in a case statement, but it would be nicer to simply detect what is supported instead of pushing overhead to the users.

if hasattr(Extension, 'Standard') and callable(getattr(Extension, 'Standard')):
    standard=instance.Standard()
else:
    standard=0

if standard == 0:
    instance.FunctionCall(arg1='foo')
elif standard == 1:
    instance.FunctionCall(arg1='foo', arg2='bar')

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文