Moin moin,
ich bin es noch mal. Danke für eure Tipps. Leider stehe ich gerade auf der Stelle. Ich versuche den Parameter des folgenden extends()-Methodenaufruf auszulesen:
# Settings for alias
extra_host_conf.setdefault('alias', []).extend(
[(u'alias1', ['host1']),
(u'alias2', ['host2']),
(u'alias3', ['host3'])])
Ich habe einige Methoden erstellt, um mir erst mal ausgeben zu lassen, welche Teile welche Typen sind:
Code: Alles auswählen
import ast
class MyVisitor(ast.NodeVisitor):
def generic_visit(self, node):
print 'Type: ', type(node).__name__
ast.NodeVisitor.generic_visit(self, node)
def visit_Load(self, node): pass
def visit_Name(self, node):
print 'Name: ', node.id
self.generic_visit(node)
def visit_Str(self, node):
print 'String: ', node.s
self.generic_visit(node)
def visit_List(self, node):
print "List: ", node.elts
self.generic_visit(node)
def visit_Tuple(self, node):
print "Tuple: ", node.elts
self.generic_visit(node)
def visit_NameConstant(self, node):
print "NameConstant: ", node.value
self.generic_visit(node)
def visit_Expr(self, node):
print "Expression: ", node.value
self.generic_visit(node)
# def visit_BinOp(self, node):
# print "Binary Operation: ", node.op
# self.generic_visit(node)
def visit_Call(self, node):
#print "Call-Arguments: ", node.args
print "ast.literal: ", ast.literal_eval(node.args[0])
self.generic_visit(node)
def visit_Attribute(self, node):
#print "Attribute-Value: ", node.value
print "Attribute: ", node.attr
self.generic_visit(node)
def main():
x = MyVisitor()
node = ast.parse(open("/scan/python/test").read())
node = ast.parse(node)
x.visit(node)
if __name__ == '__main__':
main()
Damit erhalte ich für das Eingangsbeispiel (Text) folgende Ausgabe:
Type: Module
Expression: <_ast.Call object at 0x7ff27c934fd0>
Type: Expr
ast.literal: [(u'alias1', ['host1']), (u'alias2', ['host2']), (u'alias3', ['host3'])]
Type: Call
Attribute: extend
Type: Attribute
ast.literal: alias
Type: Call
Attribute: setdefault
Type: Attribute
Name: extra_host_conf
Type: Name
String: alias
Type: Str
List: []
Type: List
List: [<_ast.Tuple object at 0x7ff27c8d4b10>, <_ast.Tuple object at 0x7ff27c8d4c10>, <_ast.Tuple object at 0x7ff27c8d4d10>]
Type: List
Tuple: [<_ast.Str object at 0x7ff27c8d4b50>, <_ast.List object at 0x7ff27c8d4b90>]
Type: Tuple
String: alias1
Type: Str
List: [<_ast.Str object at 0x7ff27c8d4bd0>]
Type: List
String: host1
Type: Str
Tuple: [<_ast.Str object at 0x7ff27c8d4c50>, <_ast.List object at 0x7ff27c8d4c90>]
Type: Tuple
String: alias2
Type: Str
List: [<_ast.Str object at 0x7ff27c8d4cd0>]
Type: List
String: host2
Type: Str
Tuple: [<_ast.Str object at 0x7ff27c8d4d50>, <_ast.List object at 0x7ff27c8d4d90>]
Type: Tuple
String: alias3
Type: Str
List: [<_ast.Str object at 0x7ff27c8d4dd0>]
Type: List
String: host3
Type: Str
Dabei ist für mich folgendes relevant:
ast.literal: [(u'alias1', ['host1']), (u'alias2', ['host2']), (u'alias3', ['host3'])]
Type: Call
Attribute: extend
Type: Attribute
ast.literal: alias
Type: Call
Attribute: setdefault
Type: Attribute
Name: extra_host_conf
Type: Name
String: alias
Type: Str
Anhand des
Namens "
extra_host_conf" könnte ich später in dessen ast-Literal springen. Nun weiß ich aber nicht, wie ich das ast-Literal dort aufrufen kann. Der Compiler sagt mir, dass das Namensobjekt kein Attribut 'args' hat.
Code: Alles auswählen
import ast
class MyVisitor(ast.NodeVisitor):
def visit_Name(self, node):
if not isinstance(node.args, ast.Name): return
if node.id == "extra_host_conf":
print ast.literal_eval(node.args[0])
self.generic_visit(node)
def main():
x = MyVisitor()
node = ast.parse(open("/scan/python/test").read())
node = ast.parse(node)
x.visit(node)
if __name__ == '__main__':
main()
Nun gut, die Alternative wäre die Methode an Hand des Attributes "setdefault" abzufangen:
Code: Alles auswählen
import ast
class MyVisitor(ast.NodeVisitor):
def visit_Call(self, node):
#print "Call-Arguments: ", node.args
#if not isinstance(node.func, ast.Name): return
if node.func.attr == "setdefault":
print "Attr vorhanden"
print ast.literal_eval(node.args[0])
self.generic_visit(node)
#
# def visit_Attribute(self, node):
# print "Attribute-Value: ", node.value
# print "Attribute: ", node.attr
# self.generic_visit(node)
def main():
x = MyVisitor()
node = ast.parse(open("/scan/python/test").read())
node = ast.parse(node)
x.visit(node)
if __name__ == '__main__':
main()
Ergebnis: "Attr vorhanden", "alias". Nun wird mir zwar der erste Parameter des Eingangsbeispiels ausgegeben, aber leider nicht der Zweite. Wenn ich den Index von ast.literal_eval(node.args[0]) auf 1 setze, denn erhalte ich eine leere Liste: []