Пока два модуля реализуют один и тот же интерфейс (классы с одинаковыми именами, методами и другими атрибутами, функции с одинаковыми именами и сигнатурами, ...), вы можете выбрать один или другой в то время, когда ваше приложение запускается, например, на основе некоторого файла конфигурации, и импортирует выбранный файл с фиксированным именем. Все остальное ваше приложение может затем использовать это фиксированное имя и, за исключением кода запуска, быть в блаженном неведении о любых махинациях, которые могли быть сделаны в начале.
Например, рассмотрим упрощенный случай:
# english.py
def greet(): return 'Hello!'
# italian.py
def greet(): return 'Ciao!'
# french.py
def greet(): return 'Salut!'
# config.py
langname = 'italian'
# startit.py
import config
import sys
lang = __import__(config.langname)
sys.modules['lang'] = lang
Теперь все остальное приложение может просто import lang
, и оно получит под этим именем модуль italian
, поэтому при вызове lang.greet()
он получит строку 'Ciao!'
. * 1010. *
Конечно, в реальной жизни у вас будет несколько модулей, каждый с несколькими функциями, классами и так далее, но общие принципы остаются очень схожими. Просто будьте особенно внимательны с модулями с квалифицированными именами (такими как foo.bar
), т. Е. С модулями, которые должны находиться в пакете (в данном случае foo
). Для них вы не можете просто использовать возвращаемое значение __import__
, но должны использовать немного более обходной подход, такой как:
import sys
def importanyasname(actualname, fakename):
__import__(actualname)
sys.modules[fakename] = sys.modules[actualname]
, то есть игнорировать возвращаемое значение __import__
и достичь правого значения для левого значения (с фактическим именем в качестве ключа) в словаре sys.modules
- , что является модулем объект, который вы ищете, и который вы можете установить обратно в sys.modules
с «поддельным именем», с помощью которого все остальные приложения смогут в любой момент безупречно импортировать его.