I'm trying to load a sub-module from a ZIP package but it won't work. How to do it right?
foo.zip
foo/
__init__.py
bar.py
test.py
import os
import zipimport
dirname = os.path.dirname(__file__)
importer = zipimport.zipimporter(os.path.join(dirname, 'foo.zip'))
print importer.is_package('foo')
print importer.load_module('foo')
print importer.load_module('foo.bar')
Output
$ python test.py
True
<module 'foo' from 'foo.zip/foo/__init__.py'>
Traceback (most recent call last):
File "test.py", line 8, in <module>
print importer.load_module('foo.bar')
zipimport.ZipImportError: can't find module 'foo.bar'
Update 2015/04/11 06:30 AM PT
The following would work, but is this the real solution to the problem? The zipimport.zipimporter
documentation explicitly states "fullname must be the fully qualified (dotted) module name." and has an is_package()
method that seems to function properly.
import os
import zipimport
dirname = os.path.dirname(__file__)
importer = zipimport.zipimporter(os.path.join(dirname, 'foo.zip'))
def load_module(name):
parts = name.split('.')
module = importer.load_module(parts[0])
full_name = parts[0]
for part in parts[1:]:
full_name += '.' + part
if not hasattr(module, '__path__'):
raise ImportError('%s' % full_name)
path = module.__path__[0]
module = zipimport.zipimporter(path).load_module(part)
return module
print load_module('foo.bar')
It will load if you change importer.load_module('foo.bar')
to importer.load_module('foo/bar')
. I am not sure why, because the documentation reads
load_module(fullname)
Load the module specified by fullname. fullname must be the fully qualified (dotted) module name. It returns the imported module, or raises ZipImportError if it wasn’t found.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With