2012-02-24 12 views
11

निम्नलिखित एक अजगर कोड ast और symtable संकुल का उपयोग करके स्निपेट है। मैं कोड को पार्स करने और प्रकारों की जांच करने की कोशिश कर रहा हूं। लेकिन वास्तविक चर संदर्भित होने के लिए ऑब्जेक्ट्स को पार करने के तरीके को समझ में नहीं आता है।अजगर ast पैकेज: traversing वस्तु पदानुक्रम

निम्नलिखित कोड एक नोडविजिटर लागू करता है, और एक फ़ंक्शन कंपाइलर को प्रस्तुत किया जाता है और संकलक द्वारा पार्स किया जाता है और अस्थिर चला जाता है। कार्य का विश्लेषण किया जा रहा है (eval_types) कुछ वस्तुओं को पारित किया गया है।

नीचे दिए गए कोड भाग हैं जो उदाहरण बनाते हैं। मैंने प्रत्येक खंड के लिए कुछ टिप्पणियां जोड़ दी हैं। कोड को चलाने के लिए, "भाग" को फिर से इकट्ठा करने की आवश्यकता है।

आयात और एक कार्य को पार्सिंग के लिए कोड के ब्लॉक को अनदेखा करने के लिए।

import inspect 
import ast 
import symtable 
from tokenize import generate_tokens, untokenize, INDENT 
from cStringIO import StringIO 

# _dedent borrowed from the myhdl package (www.myhdl.org) 
def _dedent(s): 
    """Dedent python code string.""" 

    result = [t[:2] for t in generate_tokens(StringIO(s).readline)] 
    # set initial indent to 0 if any 
    if result[0][0] == INDENT: 
     result[0] = (INDENT, '') 
    return untokenize(result) 

निम्नलिखित नोड विज़िटर है, इसमें सामान्य अनचाहे और नाम विज़िटर ओवरलोड हैं।

class NodeVisitor(ast.NodeVisitor): 
    def __init__(self, SymbolTable): 
     self.symtable = SymbolTable 
     for child in SymbolTable.get_children(): 
      self.symtable = child 
      print(child.get_symbols()) 

    def _visit_children(self, node): 
     """Determine if the node has children and visit""" 
     for _, value in ast.iter_fields(node): 
      if isinstance(value, list): 
       for item in value: 
        if isinstance(item, ast.AST): 
         print(' visit item %s' % (type(item).__name__)) 
         self.visit(item) 

      elif isinstance(value, ast.AST): 
       print(' visit value %s' % (type(value).__name__)) 
       self.visit(value) 

    def generic_visit(self, node): 
     print(type(node).__name__) 
     self._visit_children(node) 

    def visit_Name(self, node): 
     print(' variable %s type %s' % (node.id, 
             self.symtable.lookup(node.id))) 
     print(dir(self.symtable.lookup(node.id))) 

निम्नलिखित कुछ सरल वर्ग हैं जिनका उपयोग फ़ंक्शन में किया जाएगा जिसे एएसटी के साथ विश्लेषण और विश्लेषण किया जाएगा।

class MyObj(object): 
    def __init__(self): 
     self.val = None 

class MyObjFloat(object): 
    def __init__(self): 
     self.x = 1. 

class MyObjInt(object): 
    def __init__(self): 
     self.x = 1 

class MyObjObj(object): 
    def __init__(self): 
     self.xi = MyObjInt() 
     self.xf = MyObjFloat() 

निम्नलिखित, परीक्षण समारोह है eval_types समारोह समारोह है कि एएसटी के साथ विश्लेषण किया जाएगा है।

def testFunc(x,y,xo,z): 

    def eval_types(): 
     z.val = x + y + xo.xi.x + xo.xf.x 

    return eval_types 

उदाहरण निष्पादित करने के लिए कोड, फ़ंक्शन संकलित करें और विश्लेषण करें।

if __name__ == '__main__': 
    z = MyObj() 
    print(z.val) 
    f = testFunc(1, 2, MyObjObj(), z) 
    f() 
    print(z.val) 
    s = inspect.getsource(f) 
    s = _dedent(s) 
    print(type(s)) 
    print(s) 

    SymbolTable = symtable.symtable(s,'string','exec') 
    tree = ast.parse(s) 
    v = NodeVisitor(SymbolTable) 
    v.visit(tree) 

निम्नलिखित नाम नाम पर एक उदाहरण आउटपुट है।

Module 
    visit item FunctionDef 
FunctionDef 
    visit value arguments 
arguments 
    visit item Assign 
Assign 
    visit item Attribute 
Attribute 
    visit value Name 
    variable z type <symbol 'z'> 
['_Symbol__flags', '_Symbol__name', '_Symbol__namespaces', 
'_Symbol__scope', '__class__', '__delattr__', '__dict__', 
'__doc__', '__format__', '__getattribute__', '__hash__', 
'__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', 
'__repr__', '__setattr__', '__sizeof__', '__str__', 
'__subclasshook__', '__weakref__', 'get_name', 'get_namespace', 
'get_namespaces', 'is_assigned', 'is_declared_global', 
'is_free', 'is_global', 'is_imported', 'is_local', 
'is_namespace', 'is_parameter', 'is_referenced'] 

नोड आगंतुक बनाना बुरा नहीं लगता है, लेकिन मैं बाहर समझ नहीं सकता एक वस्तु पदानुक्रम पार करने के लिए कैसे। सामान्य मामले में परिवर्तनीय एक्सेस किया जा रहा है किसी ऑब्जेक्ट में गहरा दफनाया जा सकता है। अस्थिर आगंतुक से वास्तविक चर को कैसे पहुंचाया जा सकता है? मैं केवल देखता हूं कि ऑब्जेक्ट नोड पर है लेकिन परिणामस्वरूप परिवर्तनीय पहुंच क्या है कोई अतिरिक्त जानकारी नहीं है।

+1

यकीन नहीं है कि मैं जो चाहता हूं उसका पालन करता हूं। क्या आपको ".val" नहीं मिल रहा है? क्या आपने उस नोड के नीचे रिकर्सिंग करने की कोशिश की है? यह लंबे समय से है क्योंकि मैंने इसका इस्तेमाल किया था, लेकिन मुझे याद है कि आपको अपने मामले में, visit_name से visit_children को कॉल करने की आवश्यकता होगी। –

+0

@andrewcooke टिप्पणियों के लिए धन्यवाद! हां, मैं ऑब्जेक्ट्स (z.val, xo.xi.x, xo.xf.x) को पार्स करना जारी रखना चाहता हूं और कथन में उपयोग किए गए वास्तविक चर पर अधिक जानकारी निर्धारित करना चाहता हूं। सरल मामला होगा, z = x + y + xo_xi_x + xo_xf_x, जहां वेरिएबल ऑब्जेक्ट्स में एम्बेडेड (दफन नहीं) होते हैं और वेरिएबल/गुण/प्रकार के चर को उपरोक्त कोड स्निपेट में निर्धारित किया जा सकता है। मैं इन प्रकार के नोड्स पर स्पष्ट रूप से visit_children को कॉल करने के साथ प्रयोग करूंगा। एक बार फिर धन्यवाद। –

+0

एएसटी पैकेज की समझ विकसित करने वाली छोटी (धीमी) प्रगति करना। इस उदाहरण के लिए, ऑब्जेक्ट "विशेषताएँ" ** visit_Attribute ** की यात्रा करेगा। अब मुझे बस यह निर्धारित करने की आवश्यकता है कि ** visit_Name ** में कोई ऑब्जेक्ट है (बच्चे हैं?) तो visit_Attribute में समाप्त करें और पीछे की ओर काम करें (पेड़ का बैक अप लें)। –

उत्तर

2

मुझे नहीं पता कि आप अभी भी इसकी तलाश कर रहे हैं, लेकिन ऐसा लगता है कि आपको visit_Attribute जोड़ने और पीछे की ओर जाने की आवश्यकता है। आप अपने उदाहरण को यह भी जोड़ते हैं तो:

def visit_Attribute(self, node): 
    print(' attribute %s' % node.attr) 
    self._visit_children(node) 

फिर xo.xf.x के लिए उत्पादन होता है:

Add 
    visit value Attribute 
    attribute x 
    visit value Attribute 
    attribute xf 
    visit value Name 
    variable xo type <symbol 'xo'> 
    visit value Load 

निर्भर करता है कि आप इस के साथ क्या करना चाहते हैं, तो आप सिर्फ जब तक किसी सूची में गुण स्टोर करने के लिए की आवश्यकता होगी Name का सामना करना पड़ता है, फिर उन्हें उलट दें।

संबंधित मुद्दे