Уведомления

Группа в Telegram: @pythonsu

#1 Июнь 13, 2008 14:53:33

shiza
От:
Зарегистрирован: 2007-07-03
Сообщения: 1073
Репутация: +  0  -
Профиль   Отправить e-mail  

хак импорта

Отлично! Спасибо.

P.S. Есть PEP http://www.python.org/dev/peps/pep-0302/ со ссылками, насчет переписывания импортов.



Отредактировано (Июнь 13, 2008 14:55:13)

Офлайн

#2 Июнь 13, 2008 15:11:20

ZAN
От:
Зарегистрирован: 2007-06-10
Сообщения: 403
Репутация: +  10  -
Профиль   Отправить e-mail  

хак импорта

о_О
Замечательно. Буду читать =)



Офлайн

#3 Июнь 13, 2008 15:20:11

shiza
От:
Зарегистрирован: 2007-07-03
Сообщения: 1073
Репутация: +  0  -
Профиль   Отправить e-mail  

хак импорта

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

В этом способе это по другому, из-за чего модут возникнуть разные сайд-эффекты.
Например если в модуле во время импорта исполняется какой-нибудь подготовительный код (к примеру формируется устойчивый объект).



Отредактировано (Июнь 13, 2008 15:20:37)

Офлайн

#4 Июнь 13, 2008 17:17:46

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

хак импорта

нет. Внимательно прочитайте уже упомянутый 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)
Выкладываю без изменений - как он у меня сохранился. Установка хука - в последней строке



Отредактировано (Июнь 13, 2008 17:19:26)

Офлайн

#5 Июнь 13, 2008 19:16:17

bialix
От:
Зарегистрирован: 2006-07-13
Сообщения: 774
Репутация: +  1  -
Профиль   Отправить e-mail  

хак импорта

забавно. документация на Python 2.5 ничего не знает про sys.path_hooks. Когда этот механизм появился?



Офлайн

#6 Июнь 13, 2008 20:13:15

poltergeist
От:
Зарегистрирован: 2007-02-28
Сообщения: 522
Репутация: +  0  -
Профиль   Отправить e-mail  

хак импорта

оно? http://www.python.org/doc/2.3/whatsnew/section-pep302.html

… интересно:)



Отредактировано (Июнь 13, 2008 20:16:58)

Офлайн

#7 Июнь 13, 2008 20:48:00

bialix
От:
Зарегистрирован: 2006-07-13
Сообщения: 774
Репутация: +  1  -
Профиль   Отправить e-mail  

хак импорта

ага. оно. а дока на модуль sys молчит. хм.



Офлайн

#8 Июнь 13, 2008 23:04:40

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

хак импорта

Я основывался именно на PEP 302, исходя из того, что ее уже довольно давно приняли

P.S. Люблю я ПЕПы почитывать. Мозги проясняет. В том числе и отложенные/отклоненные - чтобы понимать, почему питон движется имено тем путем, который мы все наблюдаем



Отредактировано (Июнь 13, 2008 23:29:46)

Офлайн

#9 Июнь 14, 2008 02:20:11

shiza
От:
Зарегистрирован: 2007-07-03
Сообщения: 1073
Репутация: +  0  -
Профиль   Отправить e-mail  

хак импорта

Андрей Светлов
Говоря про сайд-эффект я имел ввиду способ предложенный ZAN
Насчет хука - спасибо.



Отредактировано (Июнь 14, 2008 02:36:18)

Офлайн

#10 Окт. 16, 2008 01:46:34

shiza
От:
Зарегистрирован: 2007-07-03
Сообщения: 1073
Репутация: +  0  -
Профиль   Отправить e-mail  

хак импорта

Не без кривостей, но сделал таки импорт кода из базы.
Уже месяц как успешно трудится =)

Если кому-нибудь будет сильно нужно - просите - запостю паттерн.



Отредактировано (Окт. 16, 2008 02:01:15)

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version