Reputation: 8498
For a multitude of reasons I find myself in the position of importing many python modules and wanting to iterate through each of the Classes in the module.
from capacity_hdd_parser import CapacityHDDParser
from capacity_ssd_parser import CapacitySSDParser
from checksum_parser import ChecksumParser
.
.
.
each parser inheritances from a base class and has a method I want to call on each parser
parsers = [CapacityHDDParser, CapacitySSDParser, ChecksumParser]
for parser in parsers:
parser_instance = parser()
data_returned = parser_instance.parse(logset_path)
# Do a bunch of post processing here.
My problem is that I have many parsers to go through and I feel like there has to be a way to dynamically iterate through imported class. Having to hand write each of these is not only a pain in the ass it makes the intent of my code much harder to see in the noise.
Upvotes: 3
Views: 2359
Reputation: 26160
If you don't need them in the global namespace, you could use importlib.import_module
.
from importlib import import_module
for module_name, class_name in (('capacity_hdd_parser', 'CapacityHDDParser'),
('capacity_ssd_parser', 'CapacitySSDParser'),
('checksum_parser', 'ChecksumParser')):
data_returned = getattr(import_module(module_name), class_name)().parse(logset_path)
# Other processing here
You might also want to consider consolidating your parser classes in to a single package. It would make this approach more DRY, and also probably be more Pythonic. One class per file is usually overly redundant/verbose in Python.
Upvotes: 4
Reputation: 77369
Kids, do not try to this at home:
parsers = [v for (k, v) in locals().items()
if k.endswith('Parser')]
You may make it a little bit safer with a better test condition.
[update]
The declarative approach by Silas is the safe bet:
PARSERS = {
'capacity_hdd_parser': 'CapacityHDDParser',
'capacity_ssd_parser': 'CapacitySSDParser',
'checksum_parser': 'ChecksumParser',
...
}
def load_parser(module, parser):
return getattr(importlib.import_module(module), parser)
parsers = [load_parser(*item) for item in PARSERS.items()]
Better yet, you can replace the PARSERS
dict with a config file.
Upvotes: 3
Reputation: 414795
for Parser in get_registered_parsers():
data = Parser().parse(logset_path)
Define get_registered_parsers()
by any means necessary including black magic e.g., setuptools entry_points, or yapsy (plugin architecture), or ABCs (explicit register()
function), etc.
Upvotes: 0