Phân tích cú pháp và sửa đổi cấu trúc mã chắc chắn là có thể với sự trợ giúp của ast
mô-đun và tôi sẽ hiển thị nó trong một ví dụ trong giây lát. Tuy nhiên, không thể viết lại mã nguồn đã sửa đổi chỉ với ast
mô-đun. Có các mô-đun khác có sẵn cho công việc này, chẳng hạn như một ở đây .
LƯU Ý: Ví dụ dưới đây có thể được coi là hướng dẫn giới thiệu về cách sử dụng ast
mô-đun nhưng hướng dẫn toàn diện hơn về sử dụng ast
mô-đun có sẵn ở đây tại hướng dẫn rắn Green Tree và tài liệu chính thức về ast
mô-đun .
Giới thiệu về ast
:
>>> import ast
>>> tree = ast.parse("print 'Hello Python!!'")
>>> exec(compile(tree, filename="<ast>", mode="exec"))
Hello Python!!
Bạn có thể phân tích mã python (được biểu thị bằng chuỗi) bằng cách gọi API ast.parse()
. Điều này trả về tay cầm cho cấu trúc Tóm tắt Cú pháp Cây (AST). Điều thú vị là bạn có thể biên dịch lại cấu trúc này và thực hiện nó như được hiển thị ở trên.
Một API rất hữu ích khác là ast.dump()
kết xuất toàn bộ AST ở dạng chuỗi. Nó có thể được sử dụng để kiểm tra cấu trúc cây và rất hữu ích trong việc gỡ lỗi. Ví dụ,
Trên 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)])"
Trên 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=[]))])"
Lưu ý sự khác biệt về cú pháp cho câu lệnh in trong Python 2.7 so với Python 3.5 và sự khác biệt về loại nút AST trong các cây tương ứng.
Cách sửa đổi mã bằng cách sử dụng ast
:
Bây giờ, chúng ta hãy xem một ví dụ về sửa đổi mã python theo ast
mô-đun. Công cụ chính để sửa đổi cấu trúc AST là ast.NodeTransformer
lớp. Bất cứ khi nào cần sửa đổi AST, anh ấy / cô ấy cần phải phân lớp từ nó và viết (các) Biến đổi nút tương ứng.
Ví dụ của chúng tôi, hãy thử viết một tiện ích đơn giản để chuyển đổi Python 2, in các câu lệnh thành các lệnh gọi hàm Python 3.
Tuyên bố in sang tiện ích chuyển đổi cuộc gọi vui vẻ: 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])
Tiện ích này có thể được thử trên tệp ví dụ nhỏ, chẳng hạn như dưới đây, và nó sẽ hoạt động tốt.
Kiểm tra tệp đầu vào: 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()
Xin lưu ý rằng chuyển đổi ở trên chỉ dành cho ast
mục đích hướng dẫn và trong trường hợp thực tế, người ta sẽ phải xem xét tất cả các kịch bản khác nhau, chẳng hạn như print " x is %s" % ("Hello Python")
.