JAR equivalent in Gordon McMillan's Installer

Robin Becker robin at jessikat.fsnet.co.uk
Thu Feb 14 12:56:11 EST 2002


In article <2upn6uoqotqejiji69bg8kebfacdu9oamb at 4ax.com>, Paul Moore <paul.moore at atosorigin.com>
writes
>One nice feature of Java (sorry!) is the ability to ship an application
>as a single JAR file - containing all code, resources, etc, etc. Is
>there any equivalent feature available in Python? The obvious place
>where it would be is in Gordon McMillan's Installer package, with its
>Python Archive format, but I don't think (from looking at the docs) that
>does quite what I'm after.
>
>I have no requirement to include a Python interpreter, or C extensions,
>in the archive. The code is all pure Python. But, I do want to be able
>to include support files (text files, image files for use in wxPython
>toolbars, graphics for display on screen, sound files, etc etc) which
>can be picked up from the same archive.
>
>I'm looking for something which works a bit like Java's
>ClassLoader.getResourceAsStream() (along with the necessary stuff to
>allow the stream to then be *used* as an icon/image/whatever).
>
>It seems like the sort of thing which should be possible with Python,
>but I can't find it. Did I miss something?
>
>Thanks in advance,
>Paul.
>
well his .pyz is a compressed archive form and I have been using it to compress the entire
python library. All that's required is a special importer to allow imports from such an archive
to work. I believe that the archive is allowed to contain data files as well so provided you
alter the open/read you can at least consider doing that.

The startup code I use is below. Assuming that zlib is available means
that the modules archive_rt & imputils don't need to be specially obtained
with a linked version of libz. 

In our demo we do this just after initialising
python and  before importing site. If a full python is already available
you'd only need to do this in a stub python file to get access to all of your 
modules etc.

###################################################
def _rl_readPYZ(fn):
        import zlib, imp, marshal, sys, struct
        MAGIC = 'PYZ\\0'
        TOCPOS = 8
        pymagic = imp.get_magic()
        lib = open(fn,'rb')
        if lib.read(len(MAGIC)) != MAGIC:
                raise RuntimeError, fn+' is not a valid ZArchive file'
        if lib.read(len(pymagic)) != pymagic:
                raise RuntimeError, fn+' has version mismatch to dll'
        lib.seek(TOCPOS)
        (offset,) = struct.unpack('=i', lib.read(4))
        lib.seek(offset)
        toc = marshal.load(lib)
        for name in ('imputil','archive_rt'):
                (ispkg, pos, lngth) = toc.get(name, (0, None, 0))
                if pos is None: raise ValueError, 'Module '+name+' not found'
                lib.seek(pos)
                code = marshal.loads(zlib.decompress(lib.read(lngth)))
                if ispkg: values['__path__'] = [fqname]
                is_module = isinstance(code, type(sys))
                module = is_module and code or imp.new_module(name)
                module.__dict__.update({'__file__':code.co_filename,'__iname__':name})
                sys.modules[name] = module
                if not is_module: exec code in module.__dict__
                module = sys.modules[name]
                module.__name__ = name
        import archive_rt
        sys.importers.append(archive_rt.ZlibArchive(fn, 0))
_rl_readPYZ(r'reportlab.pyz')
del _rl_readPYZ
-- 
Robin Becker



More information about the Python-list mailing list