Если ваш модуль верхнего уровня не является файлом, а упакован как каталог с __init__.py, то принятое решение почти работает, но не совсем. В Python 3.5+ необходим следующий код (обратите внимание на добавленную строку, начинающуюся с «sys.modules»):
MODULE_PATH = "/path/to/your/module/__init__.py"
MODULE_NAME = "mymodule"
spec = importlib.util.spec_from_file_location("mymodule", MODULE_PATH)
module = importlib.util.module_from_spec(spec)
sys.modules[spec.name] = module
spec.loader.exec_module(module)
Без этой строки, когда exec_module выполняется, он пытается связать относительный импорт в ваш верхний уровень __init__.py до имени модуля верхнего уровня - в этом случае «mymodule». Но «mymodule» еще не загружен, поэтому вы получите сообщение об ошибке «SystemError: Parent module« mymodule »не загружен, не может выполнять относительный импорт». Поэтому вам нужно привязать имя до его загрузки. Причиной этого является фундаментальный инвариант относительной системы импорта: «Инвариантный холдинг состоит в том, что если у вас есть sys.modules ['spam'] и sys.modules ['spam.foo'] (как и после указанного импорта ), последний должен появиться как атрибут foo предыдущего «, как обсуждалось здесь .