LINUX.ORG.RU

Как подсунуть один модуль вместо другого при импорте?

 


0

1

У меня есть своя библиотека, скажем А, один из модулей которой, скажем М, предоставляет класс C. Туева хуча данных с экземпляром этого класса сохранено на диск при помощи pickle.

Теперь я делаю новую версию, библиотеки, с новым именем B (поскольку пришлось сломать обратную совместимость), модуль M перекочевывает в эту новую версию с какими то измениями (в т.ч. со смненой имени на N), но обратная сериализация работает.

ТОчнее работала-бы, если бы удалось как то объяснить питону что это тот же модуль.

Pickle при сохранениии данных пишет имя, модуля из которого был импотртирова экземпляр класса, в моем случае это A.M. При обратной сериализации он делает

import A.M
т.е. все будет работать, пока есть библиотека A. Со временем ее не будет, и данные упс...

Я могу заранее проимпортировать B.N, и добавить в нем строчку

sys.modules['A.M'] = sys.modules['B.N']
но это не помогает - все равно питон пытается импортировать A.M, хотя мне казалось всегда что этого должно быть достаточно;-( Куда еще что нужно прописать, что бы он понял что этот модуль на самом деле уже проимпортирован?

Можно конено перегрузить функцию __import__ в B.N:

def _import_hook(*args, **kw_args):
    if args[0]=='A.M': import sys; return sys.modules[__name__]
    return _builtins_import(*args, **kw_args)    
_builtins_import, __builtins__['__import__'] = __import__, _import_hook
но че то это выглядит несколько радикальным решением... и главное, куда питон смотрит при повторном импорте модуля, как он понимает что модуль уже загружен? Мне всегда казалось что в sys.modules... ;-(

★★★★★

Последнее исправление: AIv (всего исправлений: 1)

Ты пытаешься сделать что-то очень плохое и непереносимое.

buddhist ★★★★★
()

Теперь я делаю новую версию, библиотеки, с новым именем B (поскольку пришлось сломать обратную совместимость), модуль M перекочевывает в эту новую версию с какими то измениями (в т.ч. со смненой имени на N), но обратная сериализация работает.

Таким образом ты на систему можешь поставить две библиотеки. Напиши конвертор, который их распикливает старой версией и сериализует назад уже новой.

ival ★★
()

у Девида Бизли (конечно) есть отличная презентация на тему импортов: http://www.dabeaz.com/modulepackage/.

в целях сохранения принципа минимальной неожиданности я бы инсталлировал новую версию под обоими именами, а возможно даже только под старым. выфакторь туда только код по маршаллингу, и поставляй такую совместимую версию этого пакета и с новой, и со старой версией пакета.

val-amart ★★★★★
()
Ответ на: комментарий от val-amart

Спасибо за презентацию.

Нет, я не могу инсталлировать новую версию под обеими именами, или только под старым.

AIv ★★★★★
() автор топика

Туева хуча данных с экземпляром этого класса сохранено на диск при помощи pickle.

Зачем было так делать, а потом ломать совместимость? Напиши код, который десериализует все эти данные с использованием старой библиотеки, а потом сохраняет нормально, в формате не зависящем от названия модулей.

curufinwe ★★★★★
()
Ответ на: комментарий от AIv

Неужели никак нельзя конвертнуть? Но почему?

Тогда напиши скрипт, который проходит по созданным pickle файлам и заменяет названия модулей на нужные. Это же просто текстовые файлы.

curufinwe ★★★★★
()
Ответ на: комментарий от curufinwe

Потому что гладиолус.

То, о чем вы пишете, и есть конвертация.

AIv ★★★★★
() автор топика
Ответ на: комментарий от anonymous

Это меянет имя модуля только в локальном пр-ве имен.

AIv ★★★★★
() автор топика
Ответ на: комментарий от AIv

я имею ввиду не *всю* новую версию, а только один модуль, отвечающий за pickle-unpickle. так тоже не? ну тогда импорт хук

val-amart ★★★★★
()
Ответ на: комментарий от val-amart

За pickle/unpickle отвечает стандартный cPickle;-)

В новой и тсарой версии модули A.M и B.N индентичны с точностью до имени (и какой то второстепенной косметики). Пробемы начнуться когда будет производистя unpickle старых данных в отсутствии старой версии.

В общем да, похоже остается импорт хук...

А куда все же смотрит питон при повторном импорте модуля? Должна же быть какая то таблица, раз это не sys.modules

AIv ★★★★★
() автор топика
Последнее исправление: AIv (всего исправлений: 1)

А модуль «A» загружен? Если нет, собственно поэтому через sys.modules не работает.

A1
()
Ответ на: комментарий от A1

Чорт... гипотеза хорошая но все проще - работает через sys.modules ;-( Руки что ли у меня были кривые когда в первый раз проверял...

AIv ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.