I'm trying to do a dynamic import (using "__import__()") of a submodule in web2py and it doesn't seem to be finding the submodule.
Here's an example path: web2py/app/modules/module.py <-- This works web2py/app/modules/module_folder/submodule.py <-- This won't get spotted.
Right now as a workaround I'm using 'exec()' but I'd rather not do that.
Answers to questions:
"Do you have __init__.py in module_folder?"
Yep.
"What exactly is the line of code you write to import web2py/app/modules/module_folder/submodule.py?"
mapping_module = __import__('communication_templates.mappings.%s' % module_name)
"what is the error?"
<type 'exceptions.AttributeError'> 'module' object has no attribute 'mapping_dict'
Explanation: I'm trying to get a variable named 'mapping_dict' from the module once I've loaded it.
The problem here is that __import__
does not do the most intuitive thing (neither does import
btw).
Here's what happens:
>>> import sys
>>> x = __import__('package1.package2.module')
>>> x
<module 'package1' from 'C:\\Temp\\package1\\__init__.py'>
Even though package1.package2.module
was imported, the variable returned is actually package1
.
So, to access something that is in package1.package2.module
, one has to dig down again:
>>> x.package2.module.Class
<class 'package1.package2.module.Class'>
Is it then the same as importing just package1
?
Not really:
>>> x = __import__('package1')
>>> x
<module 'package1' from 'C:\\Temp\\package1\\__init__.py'>
>>> x.package2.module.Class
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: module 'package1' has no attribute 'package2'
Well, __import__
is the same as `import, that is, these are the same:
package1 = __import__('package1.package2.module')
# is the same as:
import package1.package2.module
And:
package1 = __import__('package1')
# is the same as:
import package1
In each of those cases, you get just one local variable package1
.
In the case of importing package1.package2.module
, package2
is also imported and stored in package2
attribute of package package1
etc.
To access package1.package2.module.Class
, if package1.package2.module
is in a string:
>>> s = 'package1.package2.module'
>>> module = __import__(s)
>>> for submodule_name in s.split('.')[1:]:
... module = getattr(module, submodule_name)
...
>>> module.Class
<class 'package1.package2.module.Class'>