Найти - Пользователи
Полная версия: хак импорта
Начало » Python для экспертов » хак импорта
1 2
shiza
Отлично! Спасибо.

P.S. Есть PEP http://www.python.org/dev/peps/pep-0302/ со ссылками, насчет переписывания импортов.
ZAN
о_О
Замечательно. Буду читать =)
shiza
При импорте одного модуля из разных модулей обычным способом фактически исполнение импортируемого модуля будет происходить только один раз. Но при этом будет доступен всем импортнувшим его модулям.

В этом способе это по другому, из-за чего модут возникнуть разные сайд-эффекты.
Например если в модуле во время импорта исполняется какой-нибудь подготовительный код (к примеру формируется устойчивый объект).
Андрей Светлов
нет. Внимательно прочитайте уже упомянутый PEP. Нужно сделать свой loader и его прорегистрировать. Никаких сайд-эффектов не будет. Пример (не для базы данных). Он позволяет “прозрачно” входить в zip файлы. Т.е. любую часть проекта можно заархивировать - и питон ничего не заметит. Когда-то было важным.

import imp
import os, os.path

import zipimport

class Importer(object):
def __init__(self, path):
## print ‘__init__’, path
self._path = path
self._importers = {}
self._last_name = (None, None)
return

def _detect_zip_name(self,path,imp):
def subArray(arr,sub_arr,start):
arr_index=len(arr)-1
while start>=0:
if arr!=sub_arr: return False
arr_index-=1
start-=1
return True

imp_index=len(imp)-1
while imp_index>=0:
if subArray(path,imp,imp_index):
return (path,imp,imp)
imp_index-=1
return None



def find_module(self, fullname, path=None):
## print ‘find_module’, fullname, path
parts = fullname.split('.')
if path is None:
path = self._path

#zz = fullname.replace('.', ‘\\’)
#pos = path.find()
pathparts = path.split('\\')

result=self._detect_zip_name(pathparts,parts)
if result is None:
## print ‘matuk 2:’,pathparts, ‘ ’ ,parts
return None
zip,tail,zpack=result
## print ‘Zip:’,zip,' tail:',tail,' zpack:',zpack

‘'’
zfile = ‘\\’.join(zip)
zfile += ‘\\’+tail+'.zip'
if os.path.isfile(zfile):
print ‘find_module: found’, zfile
#zippackage = ‘.’.join(parts)
zippackage='.'.join(zpack)
_importer=self._importers.get(zippackage,None)
if _importer is None:
_importer=zipimport.zipimporter(zfile)
self._importers = _importer
_module_name='\\'.join(tail)
if _importer.find_module(_module_name) is None:
return None
self._last_name = (fullname, _importer)
print ‘IMPORTER: FULL_NAME< %s > ZIP_NAME< %s > IN_ZIP_NAME< %s >’%(path,zfile,_module_name)
return self
return None
‘'’
path = ‘\\’.join(zip)#os.path.join(*zip)
parts = tail
index=0
zippackage = ‘.’.join(zpack)
## print ‘PATH:’, path, parts
for p in parts:
path = os.path.join(path, p)
zfile = path+'.zip'
## print ‘ZFILE:’, zfile
zippackage += ‘.’+p
if os.path.isfile(zfile):
## print ‘find_module: found’, zfile
#zippackage = ‘.’.join(parts)
## print ‘ZP:’, zippackage
_importer=self._importers.get(zippackage,None)
if _importer is None:
_importer=zipimport.zipimporter(zfile)
self._importers = _importer
_module_name='\\'.join(parts)
## print ‘module name:’, _module_name
if _importer.find_module(_module_name) is None:
return None
self._last_name = (fullname, _importer)
## print ‘IMPORTER: FULL_NAME< %s > ZIP_NAME< %s > IN_ZIP_NAME< %s >’%(path,zfile,_module_name)
return self
index+=1
## print ‘find_module: not found’
return None

def load_module(self, fullname):
## print ‘load_module’, fullname

path = fullname.split('.')
impdata = self._find_importer(path)
#print fullname, impdata
#importer, left, right = impdata
importer, left, right, text_right = impdata

ispkg = self.is_package(fullname, impdata)
code = self.get_code(fullname, impdata)

mod = sys.modules.setdefault(fullname, imp.new_module(fullname))
#mod.__file__ = “<%s>” % self.__class__.__name__
mod.__file__ = os.path.join(self._path, *path)
mod.__loader__ = self
if ispkg:
mod.__path__ = [os.path.join(self._path, *left)]
#mod.__path__ =
#print self._path
## print ‘!’*10, impdata, mod.__path__
exec code in mod.__dict__
return mod

def get_data(self, path):

#print ‘get_data’, path
left = path.split('\\')
right =
while left:
zfile = ‘\\’.join(left)+'.zip'
if os.path.exists(zfile):
importer = zipimport.zipimporter(zfile)
right.insert(0, left.pop())
fname = ‘\\’.join(right)
#print ‘found’, zfile, fname
return importer.get_data(fname)
right.insert(0, left.pop())
raise IOError, ‘Cannot find file %s’%path

def is_package(self, fullname, impdata=None):
#print ‘is_package’, fullname, impdata
if impdata is None:
impdata = self._find_importer(fullname.split('.'))
importer, left, right, text_right = impdata
return importer.is_package(text_right)

def get_code(self, fullname, impdata=None):
#print ‘get_code’, fullname, impdata
if impdata is None:
impdata = self._find_importer(fullname.split('.'))
importer, left, right, text_right = impdata
return importer.get_code(text_right)

def get_source(self, fullname, impdata=None):
#print ‘get_source’, fullname, impdata
if impdata is None:
impdata = self._find_importer(fullname.split('.'))
importer, left, right, text_right = impdata
return importer.get_source(text_right)

def _find_importer(self, parts):
#print ‘_find_importer’, parts
left =
right =
importer = None
index = 0
zippackage = None
for p in parts:
left.append(p)
if zippackage is not None:
zippackage += ‘.’+p
else:
zippackage = p
importer = self._importers.get(zippackage, None)
if importer is not None:
right = parts
break
index +=1
#if importer is not None:
# break
text_right = ‘\\’.join(right)
return importer, left, right, text_right

import sys

sys.path_hooks.append(Importer)
Выкладываю без изменений - как он у меня сохранился. Установка хука - в последней строке
bialix
забавно. документация на Python 2.5 ничего не знает про sys.path_hooks. Когда этот механизм появился?
poltergeist
оно? http://www.python.org/doc/2.3/whatsnew/section-pep302.html

… интересно:)
bialix
ага. оно. а дока на модуль sys молчит. хм.
Андрей Светлов
Я основывался именно на PEP 302, исходя из того, что ее уже довольно давно приняли

P.S. Люблю я ПЕПы почитывать. Мозги проясняет. В том числе и отложенные/отклоненные - чтобы понимать, почему питон движется имено тем путем, который мы все наблюдаем
shiza
Андрей Светлов
Говоря про сайд-эффект я имел ввиду способ предложенный ZAN
Насчет хука - спасибо.
shiza
Не без кривостей, но сделал таки импорт кода из базы.
Уже месяц как успешно трудится =)

Если кому-нибудь будет сильно нужно - просите - запостю паттерн.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB