I have a module from a child package that is imported dynamically; how can I iterate over the classes that it contains?
I have been importing the module and listing the names like this:
package = current_module.__name__
package = package[:package.rindex(".")] # get the package
package = "%s.sub.%s"%(package,name) # make the name of the child
print "(loading package %s)"%package
module = __import__(package) # this succeeds
for name,obj in inspect.getmembers(module):
print name,type(obj)
This only prints module attributes and not the class types that the module defines:
__builtins__ <type 'dict'>
__doc__ <type 'NoneType'>
__file__ <type 'str'>
__name__ <type 'str'>
__package__ <type 'NoneType'>
__path__ <type 'list'>
imported_package <type 'module'>
It seems that my classes are not in the __dict__
unless the fromlist
is non-empty! The values in the from-list don't seem to be validated though; [""]
seems to work just fine, and suddenly the classes show up!
Can anyone explain why this is?
(Standard ubuntu python 2.7.1+ (r271:86832)
To load dynamically a module call import(path) as a function with an argument indicating the specifier (aka path) to a module. const module = await import(path) returns a promise that resolves to an object containing the components of the imported module. } = await import(path);
__import__() . This means all semantics of the function are derived from importlib. __import__() . The most important difference between these two functions is that import_module() returns the specified package or module (e.g. pkg. mod ), while __import__() returns the top-level package or module (e.g. pkg ).
Lazy import is a very useful feature of the Pyforest library as this feature automatically imports the library for us, if we don't use the library it won't be added. This feature is very useful to those who don't want to write the import statements again and again in their code.
Example: to create a dict that maps the names to the classes:
dict([(name, cls) for name, cls in mod.__dict__.items() if isinstance(cls, type)])
where mod is the loaded module
If you define __all__
in the module you are importing, which defines which symbols will be exported, you can iterate by selecting these items specifically.
map(module.__dict__.get, module.__all__)
import inspect
import mymodule
for name, obj in inspect.getmembers(mymodule):
if inspect.isclass(obj):
do stuff...
desired_classes = [obj for name, obj in somemodule.__dict__.items() if isinstance(obj, DesiredType)]
Inside the module you want to iterate on:
File: mymodule.py
class Dog:
VOICE = 'haou'
class Cat:
VOICE = 'meew'
class ImNotIncluded:
VOICE = 'what a shame'
__all__ = ['Dog', 'Cat']
>>> from mymodule import *
>>> Dog.VOICE
'haou'
>>> Cat.VOICE
'meew'
>>> ImNotIncluded.VOICE
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'ImNotIncluded' is not defined
Now to iterate you do:
>>> for cls in map(mymodule.__dict__.get, mymodule.__all__): cls
...
<class 'mymodule.Dog'>
<class 'mymodule.Cat'>
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