Получить значение __version__ из файла без использования imp.load_source? - PullRequest
0 голосов
/ 26 ноября 2018

Ранее я делал следующее для извлечения строки версии:

>>> 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

Ответы [ 2 ]

0 голосов
/ 26 ноября 2018

«Удобный» способ импортировать модуль - использовать 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

Наконец, несколько советов: я рекомендую поместить строку версии в отдельный текстовый файл с именем (скажем) __version__.txt и загрузить ее из __init__.py и все остальное, что нужно знать версию.Таким образом, вам не нужно выполнять код Python для чтения номера версии.Вы можете загрузить данные из таких файлов с помощью pkgutil.get_data(__package__, '__version__.txt') в __init__.py и заменить __package__ подходящим значением при вызове из другого модуля или открыть файл напрямую.get_data() возвращает bytes;вы можете захотеть вызвать .decode() для возвращаемого значения, чтобы преобразовать его в строку.

(pkgutil.get_data() может показаться окольным путем, но это требуется, если ваш код импортировано из ZIP-файла или установлено каким-либо другим экзотическим способом. Если ваш код находится в пакете пространства имен или был установлен необычным образом, get_data() может не работатьи верните None, так что вы должны проверить этот случай и избежать сбоев.)

0 голосов
/ 26 ноября 2018

Если вы просто хотите импортировать версию, я обычно выбираю utils, которые предлагаются из werkzeug;Я полагаю, что вы можете использовать следующее:

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

Вы также можете передать silent как bool, что скажет функции игнорировать ошибки импорта и вернет None, если возникнут какие-либо ошибки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...