Есть один способ, которым это может работать довольно просто, но вам придется внести несколько изменений в ваш старый пакет.
Вы можете просто создать файл в now/package/old/__init__.py
, содержащий:
__path__ = ['/absolute/path/to/old/package']
В новом пакете вы можете выполнить:
from package.old.package.subpackage.module import f as old_f
Уловка здесь в том, что старый пакет пытается импортировать свои собственные пакеты, используя абсолютный импорт, он собирается загружать вещи из новогопакеты вместо.Таким образом, старый пакет должен будет использовать только относительный импорт при импорте материалов из своего собственного пакета, или вам нужно будет добавить package.old ко всему абсолютному импорту, который делал старый пакет.
Если вы в порядке смодифицируя старые пакеты таким образом, тогда это должно быть хорошо.Если это ограничение не сработает для вас, тогда читайте дальше.
Если вы действительно, действительно уверены, что по некоторым причинам не хотите изменять старые пакеты.Тогда давайте сделаем некоторую чёрную магию, вы захотите заменить builtins.__import__
на вашу собственную версию, которая возвращает разные модули в зависимости от того, кто выполняет импорт.Вы можете выяснить, кто выполняет импорт, проверив стек вызовов.
Например, вот как вы можете это сделать (протестировано на Python 3.6):
import builtins
import inspect
import package.old
old_package_path = package.old.__path__[0]
OUR_PACKAGE_NAME = 'package'
OUR_PACKAGE_NAME_WITH_DOT = OUR_PACKAGE_NAME + '.'
def import_module(name, globs=None, locs=None, fromlist=(), level=0):
# only intercept imports for our own package from our old module
if not name.startswith(OUR_PACKAGE_NAME_WITH_DOT) or \
not inspect.stack()[1].filename.startswith(old_package_path):
return real_import(name, globs, locs, fromlist, level)
new_name = OUR_PACKAGE_NAME + '.old.' + name[len(OUR_PACKAGE_NAME_WITH_DOT):]
mod = real_import(new_name, globs, locs, fromlist, level)
return mod.old
# save the original __import__ since we'll need it to do the actual import
real_import = builtins.__import__
builtins.__import__ = import_module
builtins.__import__
вызывается для любых операторов импорта, с которыми сталкивается интерпретатор, и этот вызов не кэшируется, поэтому вы можете возвращать разные вещи при каждом вызове, даже если они используют одно и то же имя.
мой старый ответ, здесь только для исторических целей
Я не совсем понимаю, что вы пытаетесь сделать, но это, вероятно, возможно сделать в Python 3 с помощью importlib .
Вы бы просто создали загрузчик модулей, который загружает ваш модуль из явного пути к файлу.
Также есть функции invalidate_caches()
и reload()
, которые могут быть полезны, хотя они вам могут и не понадобиться.