2014-10-03 45 views
2

由于多种原因,我发现自己处于导入许多python模块的位置,并且希望遍历模块中的每个类。在Python中循环导入的类

from capacity_hdd_parser import CapacityHDDParser 
from capacity_ssd_parser import CapacitySSDParser 
from checksum_parser import ChecksumParser 
. 
. 
. 

从基类中的每个解析器遗产和有我想每个解析器调用一个方法

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. 

我的问题是,我有很多解析器经历,我觉得有有是一种动态遍历导入类的方法。不得不手写每一个这些不仅是屁股上的痛苦,它使得我的代码的意图在噪声中难以看清。

+0

hack:'对于base_class .__子类中的解析器__()' – jfs 2014-10-03 20:33:00

+1

如果您找不到完全不同的完成整体目标的方法,我建议您坚持使用当前的方法。它看起来乏味且容易出错,但元编程和操纵变量和标识符就好像它们是数据一样,可能更具风险。你目前的方法看起来简单易读,所以你可以坚持下去。虽然这看起来像[XY问题](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem)。 – skrrgwasme 2014-10-03 20:33:04

+0

@SLawson我最终的问题是,python的启动时间比运行解析器的时间要长,但这种讨论(我相信)超出了SO问题的范围。 – AlexLordThorsen 2014-10-03 20:37:46

回答

3

如果你不需要他们在全局命名空间,你可以使用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 

您可能还想考虑将您的解析器类整合到一个包中。它会使这种方法更加干燥,也可能会变得更加Pythonic。每个文件一个类通常在Python中过度冗余/冗长。

+0

+1为声明式方法。 – 2014-10-03 20:52:40

+0

@silas ray ..why在getattr(import_module(package_name),class_name)()。parse(longest_path)上使用了额外的'()'' – 2014-10-05 12:47:59

+0

实例化解析器对象的一个​​实例。 – 2014-10-05 14:14:46

2

孩子,不要尝试这种在家里:

parsers = [v for (k, v) in locals().items() 
      if k.endswith('Parser')] 

您可以将它一点点有一个更好的测试条件更安全。

[更新]

由西拉的声明方式是安全的赌注:

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()] 

更重要的是,你可以用config file更换PARSERS字典。

+2

我认为你的警告有倒退:这在家里尝试是完全正确的。不要在公司环境中做。 – skrrgwasme 2014-10-03 20:41:38

+0

所以这确实会返回所有我感兴趣的类。这个答案有什么问题? – AlexLordThorsen 2014-10-03 20:45:08

+1

问题是如果其他人在名称空间中引入以“Parser”结尾的变量,则可能会产生意外的结果。所以这是一个百万LoC企业应用程序中的一个隐藏陷阱,但对于临时丢弃代码,我倾向于放纵自己。 – 2014-10-03 20:48:19

0
for Parser in get_registered_parsers(): 
    data = Parser().parse(logset_path) 

定义任何必要的手段,包括黑魔法例如,setuptools的entry_points,或yapsy (plugin architecture),或者基本知识(显性register()功能)get_registered_parsers()