2017-02-13 45 views
0

我正在嘗試爲Python 3(toga)的UI庫編寫靜態文檔生成器。如何檢查模塊的屬性而不導入它

在項目中有子目錄:

  • iOS
    • setup.py
    • toga_iOS
      • __init__.py
      • app.py
  • mac
    • setup.py
    • toga_mac
      • __init__.py
      • app.py

我想通過目錄遍歷並獲得toga_x模塊中的__all__屬性的值。我遇到的問題是每個模塊都被設計成安裝在該平臺上,例如, Windows的一個需要一個Python包,在Windows,Mac的安裝在Mac等

如果我使用導入庫或__import__它失敗,因爲在每一個__init__.py文件將導入特定於平臺的軟件包,例如

PLATFORM_LIST = { 
    'android': 'Android', 
    'cocoa': 'Mac OS cocoa', 
    'gtk': 'GTK +' 
} 

for module, label in PLATFORM_LIST.items(): 
    print(module) 
    sys.path.append(os.path.join('../src', 
           module)) 
    module = importlib.import_module('toga_'+module) 
    sys.modules[module] = module 
    _all = getattr(module, '__all__') 

因「ImportError:No module named'android'」失敗。

有很多選項,ast,pylint,compile,inspectlib。這將是獲得__all__的價值而不必安裝所有相關模塊的最佳方法?

+0

以及如果'__all__'是動態創建的呢?(不一定它會在不同的平臺上有所不同,但可能來自多個單獨的賦值語句) –

+0

它在每個包中都被靜態聲明,作爲記錄它支持哪些API的一種方式。 –

回答

2

可以使用ast找到一個Python源文件中的靜態分配節點:

import ast 


def get_declaration_from_source(text, name="__all__"): 
    """gets a single declaration from python source code""" 
    tree = ast.parse(text) 
    #walk through each statement (more or less) in the module 
    for node in tree.body: 
     #if assigning to a single target (a = b= 5 is multiple) 
     if isinstance(node, ast.Assign) and len(node.targets)==1: 
      target = node.targets[0] 
      #if assigning to the name we are looking for 
      if isinstance(target, ast.Name) and target.id == name: 
       #use literal_eval to get the actual value, can raise ValueError if not a literal value. 
       return ast.literal_eval(node.value) 
    raise NameError("name %r was not found"%(name,)) 

可以使用random源文件爲例:如果

import random 
with open(random.__file__, "r") as f: 
    names = get_declaration_from_source(f.read()) 

>>> names 
['Random', 'seed', 'random', 'uniform', 'randint', 'choice', 'sample', 'randrange', 'shuffle', 'normalvariate', 'lognormvariate', 'expovariate', 'vonmisesvariate', 'gammavariate', 'triangular', 'gauss', 'betavariate', 'paretovariate', 'weibullvariate', 'getstate', 'setstate', 'getrandbits', 'choices', 'SystemRandom'] 

注意ast.parse可以提高SyntaxError源代碼有一個語法錯誤(編譯時可能會引發其他錯誤),並且ast.literal_eval將引發一個ValueError,如果該值不是python文字,你有評論應該不是問題,歡呼聲。

相關問題