mypy importlib模块功能(mypy importlib module functions)

编程入门 行业动态 更新时间:2024-10-25 07:21:20
mypy importlib模块功能(mypy importlib module functions)

我在运行时使用importlib导入模块。 这些模块是我的应用程序的插件,必须实现一个或多个模块级功能。 我已经开始向我的应用程序添加类型注释,我从mypy声明中收到错误

模块没有属性“generate_configuration”

其中“generate_configuration”是模块函数之一。

在此示例中,模块只需要在其中包含generate_configuration函数。 该函数采用单个dict参数。

def generate_configuration(data: Dict[str, DataFrame]) -> None: ...

我一直在寻找如何指定模块的接口,但我能找到的只是类接口。 有人能指点我一些文件说明如何做到这一点? 我的google-fu让我失败了。

加载此模块的代码如下所示。 错误由最后一行生成。

plugin_directory = os.path.join(os.path.abspath(directory), 'Configuration-Generation-Plugins') plugins = ( module_file for module_file in Path(plugin_directory).glob('*.py') ) sys.path.insert(0, plugin_directory) for plugin in plugins: plugin_module = import_module(plugin.stem) plugin_module.generate_configuration(directory, points_list)

I am using importlib to import modules at runtime. These modules are plugins for my application and must implement 1 or more module-level functions. I have started adding type annotations to my applications and I get an error from mypy stating

Module has no attribute "generate_configuration"

where "generate_configuration" is one of the module functions.

In this example, the module is only required to have a generate_configuration function in it. The function takes a single dict argument.

def generate_configuration(data: Dict[str, DataFrame]) -> None: ...

I have been searching around for how to specify the interface of a module but all I can find are class interfaces. Can someone point me to some documentation showing how to do this? My google-fu is failing me on this one.

The code that loads this module is shown below. The error is generated by the last line.

plugin_directory = os.path.join(os.path.abspath(directory), 'Configuration-Generation-Plugins') plugins = ( module_file for module_file in Path(plugin_directory).glob('*.py') ) sys.path.insert(0, plugin_directory) for plugin in plugins: plugin_module = import_module(plugin.stem) plugin_module.generate_configuration(directory, points_list)

最满意答案

importlib.import_module的类型注释只返回types.ModuleType

从类型来源 :

def import_module(name: str, package: Optional[str] = ...) -> types.ModuleType: ...

这意味着plugin_module的显示类型是Module - 它没有您的特定属性。

由于mypy是一个静态分析工具,因此无法知道该导入的返回值是否具有特定的接口。

这是我的建议:

为你的模块创建一个类型接口(它不需要实例化,它只是帮助我解决问题)

class ModuleInterface: @staticmethod def generate_configuration(data: Dict[str, DataFrame]) -> None: ...

创建一个导入模块的函数,你可能需要使用__import__ # type: ignore ,但如果使用__import__而不是__import__ ,你可以避免这个限制

def import_module_with_interface(modname: str) -> ModuleInterface: return __import__(modname, fromlist=['_trash']) # might need to ignore the type here

享受类型:)

我用来验证这个想法的示例代码:

class ModuleInterface: @staticmethod def compute_foo(bar: str) -> str: ... def import_module_with_interface(modname: str) -> ModuleInterface: return __import__(modname, fromlist=['_trash']) def myf() -> None: mod = import_module_with_interface('test2') # mod.compute_foo() # test.py:12: error: Too few arguments for "compute_foo" of "ModuleInterface" mod.compute_foo('hi')

The type annotation for importlib.import_module simply returns types.ModuleType

From the typeshed source:

def import_module(name: str, package: Optional[str] = ...) -> types.ModuleType: ...

This means that the revealed type of plugin_module is Module -- which doesn't have your specific attributes.

Since mypy is a static analysis tool, it can't know that the return value of that import has a specific interface.

Here's my suggestion:

Make a type interface for your module (it doesn't have to be instantiated, it'll just help mypy figure things out)

class ModuleInterface: @staticmethod def generate_configuration(data: Dict[str, DataFrame]) -> None: ...

Make a function which imports your module, you may need to sprinkle # type: ignore, though if you use __import__ instead of import_module you may be able to avoid this limitation

def import_module_with_interface(modname: str) -> ModuleInterface: return __import__(modname, fromlist=['_trash']) # might need to ignore the type here

Enjoy the types :)

The sample code I used to verify this idea:

class ModuleInterface: @staticmethod def compute_foo(bar: str) -> str: ... def import_module_with_interface(modname: str) -> ModuleInterface: return __import__(modname, fromlist=['_trash']) def myf() -> None: mod = import_module_with_interface('test2') # mod.compute_foo() # test.py:12: error: Too few arguments for "compute_foo" of "ModuleInterface" mod.compute_foo('hi')

更多推荐

本文发布于:2023-08-02 12:10:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1375432.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:模块   功能   importlib   mypy   module

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!