如何检测导入的python模块的方法签名
我有一个可以加载和运行扩展的 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 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论