Импортируйте произвольный исходный файл python. (Python 3.3+)
Как импортировать произвольный исходный файл python (имя файла которого может содержать любые символы и не всегда заканчивается на .py
) в Python 3.3 +?
Я использовал imp.load_module
следующим образом:
>>> import imp
>>> path = '/tmp/a-b.txt'
>>> with open(path, 'U') as f:
... mod = imp.load_module('a_b', f, path, ('.py', 'U', imp.PY_SOURCE))
...
>>> mod
<module 'a_b' from '/tmp/a-b.txt'>
Он по-прежнему работает в Python 3.3, но согласно документации imp.load_module
он устарел:
Устаревший с версии 3.3: ненужные, поскольку загрузчики должны использоваться для загрузочные модули и find_module() устарели.
Документация модуля
и imp
рекомендует использовать importlib
:
Примечание Новые программы должны использовать importlib, а не этот модуль.
Каков правильный способ загрузить произвольный исходный файл python в Python 3.3+ без использования устаревшей функции imp.load_module
?
Ответы
Ответ 1
Найдите решение из importlib
тестового кода.
Использование importlib.machinery.SourceFileLoader:
>>> import importlib.machinery
>>> loader = importlib.machinery.SourceFileLoader('a_b', '/tmp/a-b.txt')
>>> mod = loader.load_module()
>>> mod
<module 'a_b' from '/tmp/a-b.txt'>
ПРИМЕЧАНИЕ: работает только в Python 3.3 +.
UPDATE Loader.load_module
устарел с Python 3.4. Вместо этого используйте Loader.exec_module
:
>>> import types
>>> import importlib.machinery
>>> loader = importlib.machinery.SourceFileLoader('a_b', '/tmp/a-b.txt')
>>> mod = types.ModuleType(loader.name)
>>> loader.exec_module(mod)
>>> mod
<module 'a_b'>
>>> import importlib.machinery
>>> import importlib.util
>>> loader = importlib.machinery.SourceFileLoader('a_b', '/tmp/a-b.txt')
>>> spec = importlib.util.spec_from_loader(loader.name, loader)
>>> mod = importlib.util.module_from_spec(spec)
>>> loader.exec_module(mod)
>>> mod
<module 'a_b' from '/tmp/a-b.txt'>
Ответ 2
Более короткая версия решения @falsetrue:
>>> import importlib.util
>>> spec = importlib.util.spec_from_file_location('a_b', '/tmp/a-b.py')
>>> mod = importlib.util.module_from_spec(spec)
>>> spec.loader.exec_module(mod)
>>> mod
<module 'a_b' from '/tmp/a-b.txt'>
Я тестировал его с помощью Python 3.5 и 3.6.
Согласно комментариям, он не работает с произвольными расширениями файлов.