[Zope3-dev] Loading and running ZX3 from a zip file

Phillip J. Eby pje at telecommunity.com
Wed Jan 5 21:59:30 EST 2005


At 12:31 PM 1/6/05 +1100, Peter Mayne wrote:
>An idle observation...
>
>We're writing an application that will be run from a CD. ZX3 takes a while 
>to load and start from a CD, so we thought we might use Python's ability 
>to import from a zip file (PEPs 273 and 302) to cut down the amount of 
>bytes to be read from the CD.
>
>The first problem is that there are some .pyd files in ZX3, and Python 
>won't import those. This was solved by using Thomas Heller's 
>zipextimporter that can import .pyd extensions.
>
>So far so good. However, ZX3 then attempts to open various files, 
>zope/app/server/schema.xml for instance. Since this file does not exist on 
>the filesystem (the path in this case is 
>file://///C|/tmp/zope.zip/zope/app/server/schema.xml), ZX3 can't open it: 
>end of startup.
>
>After hacking my way through various file opening code replacing zope.zip 
>in the path with something else, I eventually get to
>
>     TypeError: 'zope.security.checker.Checker' object is not callable
>
>which is where I stop. :-)
>
>I'm hesitant to call ZX3's inability to load from a zipe file a bug, 
>because I don't think such a thing was envisaged. However, is it something 
>that might be considered for the (possibly distant) future, or  (as I 
>suspect) isn't it worth the trouble? Maybe in the future the PEP 302 
>__loader__ attribute could be used.

Here's the technique that PEAK uses to find a file that's "near" a module:

def packageFile(moduleName,filename):

     """Return 'naming.IStreamFactory' for 'filename' in 'moduleName' 
package"""

     module = importString(moduleName)

     if hasattr(module,'__loader__') and hasattr(module.__loader__,'get_data'):
         from peak.naming.factories.openable import ImportLoaderFactory
         return ImportLoaderFactory(module.__loader__,moduleName,filename)

     from peak.naming.factories.openable import FileFactory
     import os.path
     return FileFactory(
         filename=os.path.join(
             os.path.dirname(module.__file__), *filename.split('/')
         )
     )

It depends, of course on some IStreamFactory implementations found in 
peak.naming.factories.openable, but as a practical matter this would 
require Zope to use stream factories instead of URLs or file names for all 
file operations.  This would likely require some glue code between Zope and 
ZConfig, for example.  (PEAK subclasses ZConfig's loader classes so that 
they use PEAK's URL subsystem instead of 'urllib2', and PEAK URLs have a 
scheme called 'pkgfile:' whose URLs look like 
"pkgfile:some.package/some/path".  When opened, these call down to the code 
shown above, and eventually ZConfig sees everything all nice and proper.)

So anyway, if somebody wanted to take a crack at adding this feature to 
Zope, they could look at some of the key pieces of PEAK's solution to get 
ideas from.



More information about the Zope3-dev mailing list