从文件中获取__version__值,而不使用imp.load_source?

时间:2018-11-26 13:19:35

标签: python python-importlib

我以前已经完成了以下操作以获取版本字符串:

>>> filepath = './somemodule/__init__.py'
>>> name = 'dummy'
>>> module_source = imp.load_source(name, filepath)
>>> module_source.__version__
1.0.0

现在,当在Python 3中不推荐使用imp时(我在3.7.1上),什么是load_source的好替代品呢?它只需要std库?

在我看来这有点令人费解,load_module实际上已被弃用:

>>> from importlib.machinery import SourceFileLoader
>>> loaded = SourceFileLoader(name, filepath).load_module()
>>> loaded.__version__
1.0.0

编辑#1:

这在Import arbitrary python source file. (Python 3.3+)中进行了讨论,解决方案之一是:

>>> loader = importlib.machinery.SourceFileLoader(name, filepath)
>>> mod = types.ModuleType(loader.name)
>>> loader.exec_module(mod)
>>> mod.__version__
1.0.0

2 个答案:

答案 0 :(得分:0)

如果您只是想导入版本,我通常会选择使用utils提供的werkzeug;我相信您可以使用以下内容:

from werkzeug.utils import import_string
version = import_string('module.__version__', silent=True)

您还可以将silent作为bool传递,这将告诉该函数忽略导入错误,如果遇到任何错误,则返回None

答案 1 :(得分:0)

导入模块的“舒适”方式是使用importlib.import_module()。出于所有实际目的,这就像使用@api.model def default_department_id(self): # just an example! implement your own default # always return a recordset (even an empty one)! return self.env['my.department.model'].search([], limit=1) department_id = fields.Many2one( comodel_name="my.department.model", default=default_department_id) 语句一样。但是,它无法导入不在import中的任意文件,因此不适用于您的用例。

要直接导入文件,请sys.path文档provides此食谱:

importlib

最后一点建议:我建议将版本字符串放在一个单独的文本文件中,该文件称为(例如)import importlib.util import sys # For illustrative purposes. import tokenize file_path = tokenize.__file__ module_name = tokenize.__name__ spec = importlib.util.spec_from_file_location(module_name, file_path) module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) # Optional; only necessary if you want to be able to import the module # by name later. sys.modules[module_name] = module ,并从__version__.txt以及需要知道版本的任何其他文件中加载。这样,您无需执行Python代码即可读取版本号。您可以使用__init__.py中的pkgutil.get_data(__package__, '__version__.txt')从此类文件中加载数据,并在从另一个模块调用时将__init__.py替换为合适的值,或直接打开文件。 __package__返回get_data();您可能要在返回值上调用.decode(),以将其转换为字符串。

({bytes似乎是一种绕行的方式,但是如果您的代码是imported from a ZIP file或以其他特殊方式安装,则是必需的。如果您的代码是namespace package或是用特别不寻常的方式安装的,pkgutil.get_data()可能无法正常工作并返回get_data(),因此您应该检查这种情况并避免崩溃。)