使用 `importlib` 从 Python 模块中仅导入特定类
Posted
技术标签:
【中文标题】使用 `importlib` 从 Python 模块中仅导入特定类【英文标题】:Importing only a specific class from a Python module with `importlib` 【发布时间】:2022-01-05 21:17:49 【问题描述】:如何使用路径从 Python 模块中仅导入特定类?
我需要使用文件路径从 Python 文件中导入特定类。我无法控制文件及其完全在我的包之外。
文件.py:
class Wanted(metaclass=MyMeta):
...
class Unwanted(metaclass=MyMeta):
...
元类实现在这里不相关。但是,我会指出它是我的软件包的一部分,我可以完全控制它。
导入示例:
spec = importlib.util.spec_from_file_location(name='Wanted', location="path_to_module/mudule.py")
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
这有效,Wanted
被导入。问题是Unwanted
也被导入了。实际上,只要为name
(包括空字符串)提供any字符串值,Wanted
和Unwanted
都会从模块中导入。
这与之前的示例具有相同的效果,其中 Wanted
和 Unwanted
都被导入:
importlib.util.spec_from_file_location(name='random string', location="path_to_module/mudule.py")
我不是在寻找使用 importlib
的特定解决方案;任何合理的方式都可以。我会指出,我不需要在导入类时使用它,我只需要进行导入,然后我的元类会处理其余的事情。
【问题讨论】:
任何形式的导入都会执行整个文件。如果你不能忍受,那么这两个类不应该在同一个文件中。 @john-hen 有点断章取义,但是元类注册了它们,但是如果包含该组件的模块恰好有另一个配置指定只需要 1 个“组件”派生类这两个组件都会被执行,那是个问题。但我有我的答案,应该可以在元类中解决,我只是希望有一个更简单的解决方案。 【参考方案1】:如果我没记错的话,name 参数只是用来命名你要导入的模块。但是,更重要的是,当您导入任何模块时,您正在执行整个文件,这意味着在您的情况下,这两个类都将被创建。无论您是写from file import Wanted
、import file
还是使用任何其他形式的导入语句都无关紧要。
Python 程序由代码块构成。块是作为一个单元执行的一段 Python 程序文本。以下是块:模块、函数体和类定义。
来源:https://docs.python.org/3/reference/executionmodel.html#structure-of-a-program
【讨论】:
感谢您的意见,我有点怀疑是这种情况。有没有办法以其他方式获得所需的行为? 正如@jasonharper 所说,如果创建这两个类时不合适,它们应该位于单独的模块中,或者您应该以某种方式更改元类的实现。我不知道细节,所以我真的帮不上忙。【参考方案2】:因为您将文件命名为“file.py”:
from file import Wanted
如果您的文件在文件夹中,您可以使用:
from folder.file import Wanted
【讨论】:
感谢您的帮助。但是您的方法不起作用,正如我在“我无法控制文件及其完全在我的包之外”的问题中提到的那样。为了像您建议的那样简单地导入,该文件必须是您从中导入的包的一部分,但事实并非如此,此外,相对导入被认为是不好的做法,因为它们与运行路径相关,而不是它们所在的文件进口的。以上是关于使用 `importlib` 从 Python 模块中仅导入特定类的主要内容,如果未能解决你的问题,请参考以下文章
在 python3 中使用 importlib 动态导入时出错