1

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

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

现在,什么时候imp在 Python 3 中被弃用(我在 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:

这在导入任意 python 源文件中进行了讨论。(Python 3.3+)和出现的解决方案之一是:

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

1 回答 1

0

导入模块的“舒适”方式是使用importlib.import_module(). 出于所有实际目的,这就像使用import语句一样。但是,它不能导入不在的任意文件sys.path,因此它不适用于您的用例。

要直接导入文件,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

最后,一点建议:我建议将版本字符串放在一个名为 (say) 的单独文本文件中,然后从其他任何需要知道版本的文件__version__.txt中加载它。__init__.py这样,您无需执行 Python 代码即可读取版本号。您可以使用pkgutil.get_data(__package__, '__version__.txt')in从此类文件中加载数据__init__.py,并在从其他模块调用时替换__package__为合适的值,或直接打开文件。 get_data()返回bytes;您可能需要调用.decode()返回值将其转换为字符串。

(pkgutil.get_data()可能看起来是一种迂回的方式,但如果您的代码是从 ZIP 文件导入或以其他一些奇特的方式安装的,则它是必需的。如果您的代码位于命名空间包中或以特别不寻常的方式安装,get_data()则可能无法work 和 return None,所以你应该检查这种情况并避免崩溃。)

于 2018-11-26T14:10:09.857 回答