การแยกวิเคราะห์และปรับเปลี่ยนโครงสร้างโค้ดเป็นไปได้แน่นอนด้วยความช่วยเหลือของast
โมดูลและฉันจะแสดงในตัวอย่างในช่วงเวลา อย่างไรก็ตามการเขียนกลับซอร์สโค้ดที่ปรับเปลี่ยนนั้นไม่สามารถทำได้ด้วยast
โมดูลเพียงอย่างเดียว มีโมดูลอื่น ๆ สำหรับงานนี้เช่นหนึ่งที่นี่
หมายเหตุ: ตัวอย่างด้านล่างนี้สามารถใช้เป็นบทช่วยสอนเบื้องต้นเกี่ยวกับการใช้ast
โมดูลได้ แต่เป็นแนวทางที่ครอบคลุมมากขึ้นเกี่ยวกับการใช้งานast
โมดูลสามารถใช้ได้ที่นี่ที่Green Tree งูกวดวิชาและเอกสารอย่างเป็นทางการในast
โมดูล
บทนำสู่ ast
:
>>> import ast
>>> tree = ast.parse("print 'Hello Python!!'")
>>> exec(compile(tree, filename="<ast>", mode="exec"))
Hello Python!!
คุณสามารถแยกรหัสหลาม (แสดงในสตริง) ast.parse()
โดยเพียงแค่การเรียกร้องของ API ส่งกลับหมายเลขอ้างอิงไปยังโครงสร้างต้นไม้บทคัดย่อ (AST) น่าสนใจที่คุณสามารถคอมไพล์กลับโครงสร้างนี้และดำเนินการตามที่แสดงด้านบน
API ที่มีประโยชน์มากอีกตัวหนึ่งคือการast.dump()
ทิ้ง AST ทั้งหมดในรูปแบบสตริง มันสามารถใช้ในการตรวจสอบโครงสร้างต้นไม้และมีประโยชน์มากในการแก้ไขข้อบกพร่อง ตัวอย่างเช่น,
บน Python 2.7:
>>> import ast
>>> tree = ast.parse("print 'Hello Python!!'")
>>> ast.dump(tree)
"Module(body=[Print(dest=None, values=[Str(s='Hello Python!!')], nl=True)])"
บน Python 3.5:
>>> import ast
>>> tree = ast.parse("print ('Hello Python!!')")
>>> ast.dump(tree)
"Module(body=[Expr(value=Call(func=Name(id='print', ctx=Load()), args=[Str(s='Hello Python!!')], keywords=[]))])"
สังเกตุความแตกต่างของไวยากรณ์สำหรับคำสั่งพิมพ์ใน Python 2.7 และ Python 3.5 และความแตกต่างในประเภทของโหนด AST ในแผนผังที่เกี่ยวข้อง
วิธีแก้ไขรหัสโดยใช้ ast
:
ทีนี้ลองมาดูตัวอย่างของการดัดแปลงโค้ดไพ ธ อนตามast
โมดูล เครื่องมือหลักสำหรับการปรับเปลี่ยนโครงสร้าง AST คือast.NodeTransformer
คลาส เมื่อใดก็ตามที่ต้องการแก้ไข AST เขา / เธอต้องการซับคลาสจากมันและเขียนการแปลงโหนดตามนั้น
ตัวอย่างของเราลองเขียนยูทิลิตี้อย่างง่ายที่แปลง Python 2 พิมพ์คำสั่งเป็นการเรียกใช้ฟังก์ชัน Python 3
พิมพ์คำสั่งไปที่ยูทิลิตี้แปลงสาย Fun: print2to3.py:
#!/usr/bin/env python
'''
This utility converts the python (2.7) statements to Python 3 alike function calls before running the code.
USAGE:
python print2to3.py <filename>
'''
import ast
import sys
class P2to3(ast.NodeTransformer):
def visit_Print(self, node):
new_node = ast.Expr(value=ast.Call(func=ast.Name(id='print', ctx=ast.Load()),
args=node.values,
keywords=[], starargs=None, kwargs=None))
ast.copy_location(new_node, node)
return new_node
def main(filename=None):
if not filename:
return
with open(filename, 'r') as fp:
data = fp.readlines()
data = ''.join(data)
tree = ast.parse(data)
print "Converting python 2 print statements to Python 3 function calls"
print "-" * 35
P2to3().visit(tree)
ast.fix_missing_locations(tree)
# print ast.dump(tree)
exec(compile(tree, filename="p23", mode="exec"))
if __name__ == '__main__':
if len(sys.argv) <=1:
print ("\nUSAGE:\n\t print2to3.py <filename>")
sys.exit(1)
else:
main(sys.argv[1])
สามารถทดลองใช้งานยูทิลิตี้นี้ในไฟล์ตัวอย่างขนาดเล็กเช่นหนึ่งไฟล์ด้านล่างและควรใช้งานได้ดี
ทดสอบไฟล์อินพุต: py2.py
class A(object):
def __init__(self):
pass
def good():
print "I am good"
main = good
if __name__ == '__main__':
print "I am in main"
main()
โปรดทราบว่าการเปลี่ยนแปลงดังกล่าวข้างต้นเป็นเพียงสำหรับวัตถุประสงค์การกวดวิชาและในกรณีที่สถานการณ์จริงใครจะต้องมองไปที่สถานการณ์ที่แตกต่างกันทั้งหมดเช่นast
print " x is %s" % ("Hello Python")