[Hack] Import binary extensions from zipfiles, windows only
Thomas Heller
theller at python.net
Tue Jan 4 15:15:18 EST 2005
"PJDM" <PeterMayne at ap.spherion.com> writes:
> I'm trying to make ZopeX3 start faster by zipping up the "zope"
> directory. (Because this will be stored on a CD, having less data to
> read will make it quicker to start.)
>
> The standard python zipimporter won't work with the ZopeX3 .pyd files,
> so zipextimporter came along at just the right time. However, it
> doesn't seem to work for me (Python 2.3.4 (#53, May 25 2004, 21:17:02)
> [MSC v.1200 32 bit (Intel)] on win32, Windows XP SP2).
>
> Sample script:
> ----
> import zipextimporter
> zipextimporter.install()
>
> import sys
> print 'Hooks:\n', sys.path_hooks
>
> sys.path.append(r'C:\tmp\zope.zip')
> print 'Path:\n', sys.path
>
> # Try an innocuous import first to make sure we have the path correct.
> import zope.server
> print 'Server file:\n', zope.server.__file__
>
> # Now try a .pyd import.
> import zope.thread._zope_thread
> print 'Thread file:\n', zope.thread._zope_thread.__file__
> ----
>
> Output:
> ----
> Hooks:
> [<class 'zipextimporter.ZipExtensionImporter'>, <type
> 'zipimport.zipimporter'>]
> Path:
> ['C:\\tmp', 'C:\\WINDOWS\\system32\\python23.zip', 'C:\\tmp',
> 'C:\\opt\\Python23\\DLLs', 'C:\\opt\\Python23\\lib',
> 'C:\\opt\\Python23\\lib\\plat-win', 'C:\\opt\\Python23\\lib\\lib-tk',
> 'C:\\opt\\Python23', 'C:\\opt\\Python23\\lib\\site-packages',
> 'C:\\tmp\\zope.zip']
> Server file:
> C:\tmp\zope.zip\zope\server\__init__.py
> Traceback (most recent call last):
> File "zei.py", line 15, in ?
> import zope.thread._zope_thread
> ImportError: No module named _zope_thread
> ----
>
> The zope.zip file contains zope.thread:
> ----
> $ unzip -l zope.zip |grep zope/thread
> 0 11-08-04 11:00 zope/thread/
> 0 07-03-04 04:34 zope/thread/DEPENDENCIES.cfg
> 65 07-28-04 22:52 zope/thread/SETUP.cfg
> 994 07-03-04 04:34 zope/thread/tests.py
> 748 11-08-04 11:00 zope/thread/tests.pyc
> 748 11-08-04 11:00 zope/thread/tests.pyo
> 20480 11-07-04 00:54 zope/thread/_zope_thread.pyd
> 7838 08-17-04 17:20 zope/thread/__init__.py
> 7808 11-08-04 11:00 zope/thread/__init__.pyc
> 7808 11-08-04 11:00 zope/thread/__init__.pyo
> ----
zipextimporter, as published, doesn't handle extensions in packages.
The patch I attached at the end, may fix this - I tested it with PIL.
It may work with zope, or may not - depends on how the extensions are
structured. If there are extensions/pyds that link to other
extensions/pyds, then it will most certainly not work.
If it doesn't work, you could still try the py2exe approach:
py2exe bundles the .py modules in a zip file, and also inserts loaders
for extensions into the zip file. The loaders load the .pyd extensions
from the file system.
Thomas
<patch>
Index: zipextimporter.py
===================================================================
RCS file: /cvsroot/py2exe/py2exe/hacks/memimp/zipextimporter.py,v
retrieving revision 1.2
diff -c -r1.2 zipextimporter.py
*** zipextimporter.py 16 Dec 2004 09:29:42 -0000 1.2
--- zipextimporter.py 4 Jan 2005 20:08:08 -0000
***************
*** 50,55 ****
--- 50,56 ----
if result:
return result
+ fullname = fullname.replace(".", "\\")
for s in self._suffixes:
if (fullname + s) in self._files:
return self
***************
*** 60,72 ****
return zipimport.zipimporter.load_module(self, fullname)
except zipimport.ZipImportError:
pass
for s in self._suffixes:
path = fullname + s
if path in self._files:
# XXX should check sys.modules first ? See PEP302 on reload
# XXX maybe in C code...
code = self.get_data(path)
! mod = _memimporter.import_module(code, "init" + fullname)
mod.__file__ = "%s\\%s" % (self.archive, path)
mod.__loader__ = self
if _memimporter.get_verbose_flag():
--- 61,75 ----
return zipimport.zipimporter.load_module(self, fullname)
except zipimport.ZipImportError:
pass
+ initname = fullname.split(".")[-1]
+ fullname = fullname.replace(".", "\\")
for s in self._suffixes:
path = fullname + s
if path in self._files:
# XXX should check sys.modules first ? See PEP302 on reload
# XXX maybe in C code...
code = self.get_data(path)
! mod = _memimporter.import_module(code, "init" + initname)
mod.__file__ = "%s\\%s" % (self.archive, path)
mod.__loader__ = self
if _memimporter.get_verbose_flag():
<patch/>
More information about the Python-list
mailing list