2016-09-19 58 views
1

我有一個包含許多類的python文件。該文件看起來就像這樣:解析python文件以查找具有特定標籤的類

some code, functions and stuff... 
class A(): 
    some code... 
@label 
class B(A): 
    some code... 
@label 
class C(A): 
    some code... 
class D(A): 
    some code... 
some extra code... 

我想要做的就是讓所有具有@label他們的聲明,即在這個例子之前類的列表:[B,C]。 (這將發生在另一個文件,如果它很重要)

我到目前爲止嘗試解析文件,就像它是一個普通的文本文件(與讀取()和東西),但我得到的是類名稱而不是類本身,即(['B','C']),我不知道下一步該怎麼做。我真的希望有一個更優雅的方式。下一步,在獲得班級名單之後,我將爲每個班級激活他們所擁有的某種功能。這就是爲什麼這個班級的名字對我來說不夠。

+0

看看了'ast'模塊,它解析使用內置解析器蟒的蟒蛇文件。 – RecursivelyIronic

+0

另外[**'inspect' **](https://docs.python.org/2/library/inspect.html)。 –

+2

你有訪問/可以更改裝飾器的源代碼嗎? –

回答

2

你有兩個選擇:

  • 使用tokenize module看出來token.OP令牌與價值@,其次是token.NAME令牌label和換行符令牌之後,class。這是最輕的。

  • 使用ast module將源解析爲樹,然後使用ast.walk()函數,查找ast.ClassDef對象。如果對象的ast.Name對象在decorator_list屬性中具有id == 'label',則可以記錄name屬性。

後者可能比較容易:

import ast 

def labelled_classnames(source): 
    module = ast.parse(source) 
    for node in ast.walk(module): 
     if not isinstance(node, ast.ClassDef): 
      continue 
     if any(isinstance(n, ast.Name) and n.id == 'label' 
       for n in node.decorator_list): 
      yield node.name 

演示:

>>> demosource = ''' 
... class A(): 
...  pass 
... 
... @label 
... class B(A): 
...  pass 
... 
... @label 
... class C(A): 
...  pass 
... 
... class D(A): 
...  pass 
... ''' 
>>> list(labelled_classnames(demosource)) 
['B', 'C']