2014-10-03 81 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()