Mem-parsing dan memodifikasi struktur kode tentu dimungkinkan dengan bantuan ast
modul dan saya akan menunjukkannya dalam sebuah contoh sebentar lagi. Namun, menulis kembali kode sumber yang dimodifikasi tidak dimungkinkan hanya dengan ast
modul. Ada modul lain yang tersedia untuk pekerjaan ini seperti yang ada di sini .
CATATAN: Contoh di bawah ini dapat diperlakukan sebagai tutorial pengantar tentang penggunaan ast
modul tetapi panduan yang lebih komprehensif tentang penggunaan ast
modul tersedia di sini di tutorial ular Pohon Hijau dan dokumentasi resmi tentang ast
modul .
Pengantar ast
:
>>> import ast
>>> tree = ast.parse("print 'Hello Python!!'")
>>> exec(compile(tree, filename="<ast>", mode="exec"))
Hello Python!!
Anda dapat menguraikan kode python (direpresentasikan dalam string) hanya dengan memanggil API ast.parse()
. Ini mengembalikan pegangan ke struktur Pohon Sintaksis Abstrak (AST). Menariknya Anda dapat mengkompilasi kembali struktur ini dan menjalankannya seperti yang ditunjukkan di atas.
API lain yang sangat berguna adalah ast.dump()
yang membuang seluruh AST dalam bentuk string. Ini dapat digunakan untuk memeriksa struktur pohon dan sangat membantu dalam debugging. Sebagai contoh,
Pada 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)])"
Pada 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=[]))])"
Perhatikan perbedaan sintaks untuk pernyataan cetak dalam Python 2.7 vs Python 3.5 dan perbedaan jenis AST node di pohon masing-masing.
Cara memodifikasi kode menggunakan ast
:
Sekarang, mari kita lihat contoh modifikasi kode python oleh ast
modul. Alat utama untuk memodifikasi struktur AST adalah ast.NodeTransformer
kelas. Setiap kali seseorang perlu memodifikasi AST, dia perlu subkelas darinya dan menulis Node Transformation (s) yang sesuai.
Sebagai contoh kita, mari kita coba menulis sebuah utilitas sederhana yang mengubah Python 2, mencetak pernyataan ke panggilan fungsi Python 3.
Pernyataan cetak ke Utilitas konverter panggilan menyenangkan: 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])
Utilitas ini dapat dicoba pada file contoh kecil, seperti yang di bawah ini, dan itu akan berfungsi dengan baik.
File Input Uji: 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()
Harap dicatat bahwa transformasi di atas hanya untuk ast
tujuan tutorial dan dalam skenario nyata seseorang harus melihat semua skenario yang berbeda seperti print " x is %s" % ("Hello Python")
.