പൈത്തണിന്റെ ast മൊഡ്യൂളിന്റെ ശക്തി കണ്ടെത്തൂ. അബ്സ്ട്രാക്റ്റ് സിൻ്റാക്സ് ട്രീ ഉപയോഗിച്ച് പൈത്തൺ കോഡ് വിശകലനം ചെയ്യാനും, മാറ്റം വരുത്താനും, സൃഷ്ടിക്കാനും പഠിക്കുക.
പൈത്തൺ Ast മൊഡ്യൂൾ: അബ്സ്ട്രാക്റ്റ് സിൻ്റാക്സ് ട്രീ മാനിപ്പുലേഷൻ ലളിതമാക്കുന്നു
പൈത്തൺ കോഡിന്റെ അബ്സ്ട്രാക്റ്റ് സിൻ്റാക്സ് ട്രീ (AST) യുമായി സംവദിക്കാൻ പൈത്തൺ ast
മൊഡ്യൂൾ ശക്തമായ ഒരു മാർഗ്ഗം നൽകുന്നു. AST എന്നത് സോഴ്സ് കോഡിന്റെ സിൻ്റാക്റ്റിക് ഘടനയുടെ ഒരു ട്രീ രൂപീകരണമാണ്, ഇത് പൈത്തൺ കോഡ് പ്രോഗ്രാമാറ്റിക്കായി വിശകലനം ചെയ്യാനും, മാറ്റം വരുത്താനും, സൃഷ്ടിക്കാനും സാധ്യമാക്കുന്നു. ഇത് കോഡ് വിശകലന ടൂളുകൾ, ഓട്ടോമേറ്റഡ് റിഫാക്ടറിംഗ്, സ്റ്റാറ്റിക് വിശകലനം, ഇഷ്ടാനുസൃത ഭാഷാ വിപുലീകരണങ്ങൾ എന്നിവയുൾപ്പെടെ വിവിധ ആപ്ലിക്കേഷനുകളിലേക്ക് വഴിയൊരുക്കുന്നു. ഈ ലേഖനം ast
മൊഡ്യൂളിന്റെ അടിസ്ഥാനകാര്യങ്ങളിലൂടെ നിങ്ങളെ നയിക്കുകയും, അതിൻ്റെ കഴിവുകളെക്കുറിച്ചുള്ള പ്രായോഗിക ഉദാഹരണങ്ങളും ഉൾക്കാഴ്ചകളും നൽകുകയും ചെയ്യും.
എന്താണ് അബ്സ്ട്രാക്റ്റ് സിൻ്റാക്സ് ട്രീ (AST)?
ast
മൊഡ്യൂളിലേക്ക് കടക്കുന്നതിന് മുൻപ്, എന്താണ് ഒരു അബ്സ്ട്രാക്റ്റ് സിൻ്റാക്സ് ട്രീ എന്ന് മനസ്സിലാക്കാം. ഒരു പൈത്തൺ ഇൻ്റർപ്രെറ്റർ നിങ്ങളുടെ കോഡ് പ്രവർത്തിപ്പിക്കുമ്പോൾ, ആദ്യപടി കോഡിനെ ഒരു AST ആയി പാർസ് ചെയ്യുക എന്നതാണ്. ഈ ട്രീ ഘടന കോഡിന്റെ സിൻ്റാക്റ്റിക് ഘടകങ്ങളായ ഫംഗ്ഷനുകൾ, ക്ലാസുകൾ, ലൂപ്പുകൾ, എക്സ്പ്രഷനുകൾ, ഓപ്പറേറ്ററുകൾ എന്നിവയെ അവയുടെ ബന്ധങ്ങളോടൊപ്പം പ്രതിനിധീകരിക്കുന്നു. AST വൈറ്റ്സ്പേസുകളും കമൻ്റുകളും പോലുള്ള അപ്രസക്തമായ വിശദാംശങ്ങൾ ഒഴിവാക്കി, അവശ്യമായ ഘടനാപരമായ വിവരങ്ങളിൽ ശ്രദ്ധ കേന്ദ്രീകരിക്കുന്നു. ഈ രീതിയിൽ കോഡിനെ പ്രതിനിധീകരിക്കുന്നതിലൂടെ, പ്രോഗ്രാമുകൾക്ക് കോഡിനെ വിശകലനം ചെയ്യാനും കൈകാര്യം ചെയ്യാനും സാധിക്കുന്നു, ഇത് പല സാഹചര്യങ്ങളിലും വളരെ പ്രയോജനകരമാണ്.
ast
മൊഡ്യൂൾ ഉപയോഗിച്ച് ആരംഭിക്കുന്നു
ast
മൊഡ്യൂൾ പൈത്തണിന്റെ സ്റ്റാൻഡേർഡ് ലൈബ്രറിയുടെ ഭാഗമാണ്, അതിനാൽ അധിക പാക്കേജുകളൊന്നും ഇൻസ്റ്റാൾ ചെയ്യേണ്ടതില്ല. ഇത് ഉപയോഗിക്കാൻ തുടങ്ങാൻ, സിമ്പിളായി ഇംപോർട്ട് ചെയ്യുക:
import ast
ast
മൊഡ്യൂളിന്റെ പ്രധാന ഫംഗ്ഷൻ ast.parse()
ആണ്, ഇത് ഒരു പൈത്തൺ കോഡിന്റെ സ്ട്രിംഗ് ഇൻപുട്ടായി എടുക്കുകയും ഒരു AST ഒബ്ജക്റ്റ് നൽകുകയും ചെയ്യുന്നു.
code = """
def add(x, y):
return x + y
"""
ast_tree = ast.parse(code)
print(ast_tree)
ഇത് <_ast.Module object at 0x...>
എന്നപോലെയുള്ള ഒരു ഔട്ട്പുട്ട് നൽകും. ഈ ഔട്ട്പുട്ട് പ്രത്യേകിച്ച് വിവരങ്ങൾ നൽകുന്നില്ലെങ്കിലും, കോഡ് വിജയകരമായി ഒരു AST ആയി പാർസ് ചെയ്തുവെന്ന് ഇത് സൂചിപ്പിക്കുന്നു. ast_tree
ഒബ്ജക്റ്റിൽ ഇപ്പോൾ പാർസ് ചെയ്ത കോഡിന്റെ മുഴുവൻ ഘടനയും അടങ്ങിയിരിക്കുന്നു.
AST വിശകലനം
AST-യുടെ ഘടന മനസ്സിലാക്കാൻ, നമുക്ക് ast.dump()
ഫംഗ്ഷൻ ഉപയോഗിക്കാം. ഈ ഫംഗ്ഷൻ ട്രീയെ പുനരാവർത്തനപരമായി സഞ്ചരിക്കുകയും ഓരോ നോഡിന്റെയും വിശദമായ രൂപം പ്രിൻ്റ് ചെയ്യുകയും ചെയ്യുന്നു.
code = """
def add(x, y):
return x + y
"""
ast_tree = ast.parse(code)
print(ast.dump(ast_tree, indent=4))
ഔട്ട്പുട്ട് ഇതായിരിക്കും:
Module(
body=[
FunctionDef(
name='add',
args=arguments(
posonlyargs=[],
args=[
arg(arg='x', annotation=None, type_comment=None),
arg(arg='y', annotation=None, type_comment=None)
],
kwonlyargs=[],
kw_defaults=[],
defaults=[]
),
body=[
Return(
value=BinOp(
left=Name(id='x', ctx=Load()),
op=Add(),
right=Name(id='y', ctx=Load())
)
)
],
decorator_list=[],
returns=None,
type_comment=None
)
],
type_ignores=[]
)
ഈ ഔട്ട്പുട്ട് കോഡിന്റെ ശ്രേണീപരമായ ഘടന കാണിക്കുന്നു. നമുക്ക് ഇത് വിശദീകരിക്കാം:
Module
: മുഴുവൻ മൊഡ്യൂളിനെയും പ്രതിനിധീകരിക്കുന്ന റൂട്ട് നോഡ്.body
: മൊഡ്യൂളിലെ സ്റ്റേറ്റ്മെൻ്റുകളുടെ ഒരു ലിസ്റ്റ്.FunctionDef
: ഒരു ഫംഗ്ഷൻ നിർവചനം പ്രതിനിധീകരിക്കുന്നു. അതിൻ്റെ ആട്രിബ്യൂട്ടുകൾ ഇവയാണ്:name
: ഫംഗ്ഷൻ്റെ പേര് ('add').args
: ഫംഗ്ഷൻ്റെ ആർഗ്യുമെൻ്റുകൾ.arguments
: ഫംഗ്ഷൻ്റെ ആർഗ്യുമെൻ്റുകളെക്കുറിച്ചുള്ള വിവരങ്ങൾ അടങ്ങിയിരിക്കുന്നു.arg
: ഒരു ആർഗ്യുമെൻ്റ് (ഉദാഹരണത്തിന്, 'x', 'y') പ്രതിനിധീകരിക്കുന്നു.body
: ഫംഗ്ഷൻ്റെ ബോഡി (പ്രസ്താവനകളുടെ ഒരു ലിസ്റ്റ്).Return
: ഒരു റിട്ടേൺ സ്റ്റേറ്റ്മെൻ്റിനെ പ്രതിനിധീകരിക്കുന്നു.value
: തിരികെ നൽകുന്ന മൂല്യം.BinOp
: ഒരു ബൈനറി ഓപ്പറേഷനെ (ഉദാഹരണത്തിന്, x + y) പ്രതിനിധീകരിക്കുന്നു.left
: ഇടതുവശത്തുള്ള ഓപ്പറാൻഡ് (ഉദാഹരണത്തിന്, 'x').op
: ഓപ്പറേറ്റർ (ഉദാഹരണത്തിന്, 'Add').right
: വലതുവശത്തുള്ള ഓപ്പറാൻഡ് (ഉദാഹരണത്തിന്, 'y').
AST-യിലൂടെ സഞ്ചരിക്കുന്നു
AST-യിലൂടെ സഞ്ചരിക്കാൻ ast
മൊഡ്യൂൾ ast.NodeVisitor
ക്ലാസ് നൽകുന്നു. ast.NodeVisitor
നെ സബ്ക്ലാസ് ചെയ്യുകയും അതിൻ്റെ മെത്തേഡുകൾ ഓവർറൈഡ് ചെയ്യുകയും ചെയ്യുന്നതിലൂടെ, സഞ്ചാര വേളയിൽ കണ്ടുമുട്ടുന്ന പ്രത്യേക നോഡ് തരങ്ങളെ പ്രോസസ്സ് ചെയ്യാൻ നിങ്ങൾക്ക് കഴിയും. ഇത് കോഡ് ഘടന വിശകലനം ചെയ്യാനും, പ്രത്യേക പാറ്റേണുകൾ തിരിച്ചറിയാനും, വിവരങ്ങൾ വേർതിരിച്ചെടുക്കാനും സഹായകമാണ്.
import ast
class FunctionNameExtractor(ast.NodeVisitor):
def __init__(self):
self.function_names = []
def visit_FunctionDef(self, node):
self.function_names.append(node.name)
code = """
def add(x, y):
return x + y
def subtract(x, y):
return x - y
"""
ast_tree = ast.parse(code)
extractor = FunctionNameExtractor()
extractor.visit(ast_tree)
print(extractor.function_names) # Output: ['add', 'subtract']
ഈ ഉദാഹരണത്തിൽ, FunctionNameExtractor
എന്നത് ast.NodeVisitor
-ൽ നിന്ന് ഇൻഹെറിറ്റ് ചെയ്യുകയും visit_FunctionDef
മെത്തേഡ് ഓവർറൈഡ് ചെയ്യുകയും ചെയ്യുന്നു. AST-യിലെ ഓരോ ഫംഗ്ഷൻ നിർവചന നോഡിനും ഈ മെത്തേഡ് വിളിക്കപ്പെടുന്നു. ഫംഗ്ഷൻ്റെ പേര് function_names
ലിസ്റ്റിലേക്ക് ഈ മെത്തേഡ് ചേർക്കുന്നു. visit()
മെത്തേഡ് AST-യിലൂടെയുള്ള സഞ്ചാരം ആരംഭിക്കുന്നു.
ഉദാഹരണം: എല്ലാ വേരിയബിൾ അസൈൻമെൻ്റുകളും കണ്ടെത്തുന്നു
import ast
class VariableAssignmentFinder(ast.NodeVisitor):
def __init__(self):
self.assignments = []
def visit_Assign(self, node):
for target in node.targets:
if isinstance(target, ast.Name):
self.assignments.append(target.id)
code = """
x = 10
y = x + 5
message = "hello"
"""
ast_tree = ast.parse(code)
finder = VariableAssignmentFinder()
finder.visit(ast_tree)
print(finder.assignments) # Output: ['x', 'y', 'message']
ഈ ഉദാഹരണം കോഡിലെ എല്ലാ വേരിയബിൾ അസൈൻമെൻ്റുകളും കണ്ടെത്തുന്നു. ഓരോ അസൈൻമെൻ്റ് സ്റ്റേറ്റ്മെൻ്റിനും visit_Assign
മെത്തേഡ് വിളിക്കപ്പെടുന്നു. ഇത് അസൈൻമെൻ്റിൻ്റെ ടാർഗെറ്റുകളിലൂടെ സഞ്ചരിക്കുകയും, ഒരു ടാർഗെറ്റ് ഒരു ലളിതമായ പേരാണെങ്കിൽ (ast.Name
), ആ പേര് assignments
ലിസ്റ്റിലേക്ക് ചേർക്കുകയും ചെയ്യുന്നു.
AST മാറ്റം വരുത്തുന്നു
ast
മൊഡ്യൂൾ നിങ്ങൾക്ക് AST മാറ്റം വരുത്താനും അനുവദിക്കുന്നു. നിലവിലുള്ള നോഡുകൾ മാറ്റാനോ, പുതിയ നോഡുകൾ ചേർക്കാനോ, അല്ലെങ്കിൽ നോഡുകൾ പൂർണ്ണമായും നീക്കം ചെയ്യാനോ നിങ്ങൾക്ക് കഴിയും. AST മാറ്റം വരുത്താൻ, നിങ്ങൾ ast.NodeTransformer
ക്ലാസ് ഉപയോഗിക്കുന്നു. ast.NodeVisitor
ന് സമാനമായി, നിങ്ങൾ ast.NodeTransformer
നെ സബ്ക്ലാസ് ചെയ്യുകയും പ്രത്യേക നോഡ് തരങ്ങൾ മാറ്റം വരുത്താൻ അതിൻ്റെ മെത്തേഡുകൾ ഓവർറൈഡ് ചെയ്യുകയും ചെയ്യുന്നു. പ്രധാന വ്യത്യാസം, ast.NodeTransformer
മെത്തേഡുകൾ മാറ്റം വരുത്തിയ നോഡ് (അല്ലെങ്കിൽ അതിനെ മാറ്റിസ്ഥാപിക്കാൻ ഒരു പുതിയ നോഡ്) തിരികെ നൽകണം എന്നതാണ്. ഒരു മെത്തേഡ് None
തിരികെ നൽകുകയാണെങ്കിൽ, ആ നോഡ് AST-യിൽ നിന്ന് നീക്കം ചെയ്യപ്പെടും.
AST മാറ്റം വരുത്തിയ ശേഷം, compile()
ഫംഗ്ഷൻ ഉപയോഗിച്ച് അതിനെ എക്സിക്യൂട്ടബിൾ പൈത്തൺ കോഡിലേക്ക് കംപൈൽ ചെയ്യേണ്ടതുണ്ട്.
import ast
class AddOneTransformer(ast.NodeTransformer):
def visit_Num(self, node):
return ast.Num(n=node.n + 1)
code = """
x = 10
y = 20
"""
ast_tree = ast.parse(code)
transformer = AddOneTransformer()
new_ast_tree = transformer.visit(ast_tree)
new_code = compile(new_ast_tree, '<string>', 'exec')
# Execute the modified code
exec(new_code)
print(x) # Output: 11
print(y) # Output: 21
ഈ ഉദാഹരണത്തിൽ, AddOneTransformer
എന്നത് ast.NodeTransformer
-ൽ നിന്ന് ഇൻഹെറിറ്റ് ചെയ്യുകയും visit_Num
മെത്തേഡ് ഓവർറൈഡ് ചെയ്യുകയും ചെയ്യുന്നു. ഓരോ സംഖ്യാപരമായ ലിറ്ററൽ നോഡിനും (ast.Num
) ഈ മെത്തേഡ് വിളിക്കപ്പെടുന്നു. ഈ മെത്തേഡ്, മൂല്യം 1 വർദ്ധിപ്പിച്ച് ഒരു പുതിയ ast.Num
നോഡ് സൃഷ്ടിക്കുന്നു. visit()
മെത്തേഡ് മാറ്റം വരുത്തിയ AST തിരികെ നൽകുന്നു.
compile()
ഫംഗ്ഷൻ മാറ്റം വരുത്തിയ AST, ഒരു ഫയലിന്റെ പേര് (ഈ സാഹചര്യത്തിൽ <string>
, കോഡ് ഒരു സ്ട്രിംഗിൽ നിന്നാണ് വരുന്നതെന്ന് സൂചിപ്പിക്കുന്നു), ഒരു എക്സിക്യൂഷൻ മോഡ് (ഒരു കോഡ് ബ്ലോക്ക് എക്സിക്യൂട്ട് ചെയ്യാൻ 'exec'
) എന്നിവയെടുക്കുന്നു. ഇത് exec()
ഫംഗ്ഷൻ ഉപയോഗിച്ച് എക്സിക്യൂട്ട് ചെയ്യാൻ കഴിയുന്ന ഒരു കോഡ് ഒബ്ജക്റ്റ് നൽകുന്നു.
ഉദാഹരണം: ഒരു വേരിയബിൾ പേര് മാറ്റുന്നു
import ast
class VariableNameReplacer(ast.NodeTransformer):
def __init__(self, old_name, new_name):
self.old_name = old_name
self.new_name = new_name
def visit_Name(self, node):
if node.id == self.old_name:
return ast.Name(id=self.new_name, ctx=node.ctx)
return node
code = """
def multiply_by_two(number):
return number * 2
result = multiply_by_two(5)
print(result)
"""
ast_tree = ast.parse(code)
replacer = VariableNameReplacer('number', 'num')
new_ast_tree = replacer.visit(ast_tree)
new_code = compile(new_ast_tree, '<string>', 'exec')
# Execute the modified code
exec(new_code)
ഈ ഉദാഹരണം 'number'
എന്ന വേരിയബിൾ പേരിന്റെ എല്ലാ സംഭവങ്ങളെയും 'num'
എന്ന് മാറ്റുന്നു. VariableNameReplacer
പഴയതും പുതിയതുമായ പേരുകൾ ആർഗ്യുമെൻ്റുകളായി എടുക്കുന്നു. ഓരോ പേര് നോഡിനും visit_Name
മെത്തേഡ് വിളിക്കപ്പെടുന്നു. നോഡിന്റെ ഐഡൻ്റിഫയർ പഴയ പേരുമായി പൊരുത്തപ്പെടുകയാണെങ്കിൽ, അത് പുതിയ പേരും അതേ കോൺടെക്സ്റ്റും (node.ctx
) ഉള്ള ഒരു പുതിയ ast.Name
നോഡ് സൃഷ്ടിക്കുന്നു. കോൺടെക്സ്റ്റ് പേര് എങ്ങനെ ഉപയോഗിക്കുന്നു എന്ന് സൂചിപ്പിക്കുന്നു (ഉദാഹരണത്തിന്, ലോഡിംഗ്, സ്റ്റോറിംഗ്).
ഒരു AST-യിൽ നിന്ന് കോഡ് ഉണ്ടാക്കുന്നു
compile()
ഒരു AST-യിൽ നിന്ന് കോഡ് എക്സിക്യൂട്ട് ചെയ്യാൻ നിങ്ങളെ അനുവദിക്കുമ്പോൾ, അത് കോഡിനെ ഒരു സ്ട്രിംഗായി ലഭിക്കാനുള്ള ഒരു മാർഗ്ഗം നൽകുന്നില്ല. ഒരു AST-യിൽ നിന്ന് പൈത്തൺ കോഡ് ഉണ്ടാക്കാൻ, നിങ്ങൾക്ക് astunparse
ലൈബ്രറി ഉപയോഗിക്കാം. ഈ ലൈബ്രറി സ്റ്റാൻഡേർഡ് ലൈബ്രറിയുടെ ഭാഗമല്ല, അതിനാൽ നിങ്ങൾ ആദ്യം ഇത് ഇൻസ്റ്റാൾ ചെയ്യണം:
pip install astunparse
തുടർന്ന്, ഒരു AST-യിൽ നിന്ന് കോഡ് ഉണ്ടാക്കാൻ നിങ്ങൾക്ക് astunparse.unparse()
ഫംഗ്ഷൻ ഉപയോഗിക്കാം.
import ast
import astunparse
code = """
def add(x, y):
return x + y
"""
ast_tree = ast.parse(code)
generated_code = astunparse.unparse(ast_tree)
print(generated_code)
ഔട്ട്പുട്ട് ഇതായിരിക്കും:
def add(x, y):
return (x + y)
ശ്രദ്ധിക്കുക: (x + y)
എന്നതിന് ചുറ്റുമുള്ള ബ്രാക്കറ്റുകൾ astunparse
ചേർത്തതാണ്, ഇത് ശരിയായ ഓപ്പറേറ്റർ മുൻഗണന ഉറപ്പാക്കുന്നു. ഈ ബ്രാക്കറ്റുകൾ കർശനമായി ആവശ്യമില്ലായിരിക്കാം, പക്ഷേ അവ കോഡിന്റെ കൃത്യത ഉറപ്പാക്കുന്നു.
ഉദാഹരണം: ഒരു ലളിതമായ ക്ലാസ് ഉണ്ടാക്കുന്നു
import ast
import astunparse
class_name = 'MyClass'
method_name = 'my_method'
# Create the class definition node
class_def = ast.ClassDef(
name=class_name,
bases=[],
keywords=[],
body=[
ast.FunctionDef(
name=method_name,
args=ast.arguments(
posonlyargs=[],
args=[],
kwonlyargs=[],
kw_defaults=[],
defaults=[]
),
body=[
ast.Pass()
],
decorator_list=[],
returns=None,
type_comment=None
)
],
decorator_list=[]
)
# Create the module node containing the class definition
module = ast.Module(body=[class_def], type_ignores=[])
# Generate the code
code = astunparse.unparse(module)
print(code)
ഈ ഉദാഹരണം താഴെ പറയുന്ന പൈത്തൺ കോഡ് ഉണ്ടാക്കുന്നു:
class MyClass:
def my_method():
pass
ഒരു AST തുടക്കം മുതൽ എങ്ങനെ നിർമ്മിക്കാമെന്നും അതിൽ നിന്ന് എങ്ങനെ കോഡ് ഉണ്ടാക്കാമെന്നും ഇത് കാണിക്കുന്നു. കോഡ് ജനറേഷൻ ടൂളുകൾക്കും മെറ്റാപ്രോഗ്രാമിംഗിനും ഈ സമീപനം ശക്തമാണ്.
ast
മൊഡ്യൂളിൻ്റെ പ്രായോഗിക ഉപയോഗങ്ങൾ
ast
മൊഡ്യൂളിന് നിരവധി പ്രായോഗിക ഉപയോഗങ്ങളുണ്ട്, അതിൽ ഉൾപ്പെടുന്നത്:
- കോഡ് വിശകലനം: ശൈലീപരമായ ലംഘനങ്ങൾ, സുരക്ഷാ പ്രശ്നങ്ങൾ, അല്ലെങ്കിൽ പ്രവർത്തനക്ഷമതയിലെ തടസ്സങ്ങൾ എന്നിവയ്ക്കായി കോഡ് വിശകലനം ചെയ്യുന്നു. ഉദാഹരണത്തിന്, ഒരു വലിയ പ്രോജക്റ്റിൽ കോഡിംഗ് സ്റ്റാൻഡേർഡുകൾ നടപ്പിലാക്കാൻ നിങ്ങൾക്ക് ഒരു ടൂൾ എഴുതാൻ കഴിയും.
- ഓട്ടോമേറ്റഡ് റിഫാക്ടറിംഗ്: വേരിയബിളുകളുടെ പേരുമാറ്റുക, മെത്തേഡുകൾ വേർതിരിച്ചെടുക്കുക, അല്ലെങ്കിൽ പുതിയ ഭാഷാ സവിശേഷതകൾ ഉപയോഗിക്കാൻ കോഡ് മാറ്റുക തുടങ്ങിയ കാര്യങ്ങൾ ഓട്ടോമേറ്റ് ചെയ്യുക.
rope
പോലുള്ള ടൂളുകൾ ശക്തമായ റിഫാക്ടറിംഗ് കഴിവുകൾക്കായി AST-കളെ ഉപയോഗിക്കുന്നു. - സ്റ്റാറ്റിക് വിശകലനം: കോഡ് യഥാർത്ഥത്തിൽ പ്രവർത്തിപ്പിക്കാതെ തന്നെ അതിലെ തെറ്റുകളോ ബഗുകളോ തിരിച്ചറിയുക.
pylint
,flake8
പോലുള്ള ടൂളുകൾ പ്രശ്നങ്ങൾ കണ്ടെത്താൻ AST വിശകലനം ഉപയോഗിക്കുന്നു. - കോഡ് ജനറേഷൻ: ടെംപ്ലേറ്റുകളോ സ്പെസിഫിക്കേഷനുകളോ അടിസ്ഥാനമാക്കി കോഡ് സ്വയമേവ നിർമ്മിക്കുക. ആവർത്തന സ്വഭാവമുള്ള കോഡ് ഉണ്ടാക്കാനോ വ്യത്യസ്ത പ്ലാറ്റ്ഫോമുകൾക്കായി കോഡ് ഉണ്ടാക്കാനോ ഇത് സഹായകമാണ്.
- ഭാഷാ വിപുലീകരണങ്ങൾ: പൈത്തൺ കോഡിനെ വ്യത്യസ്ത രൂപങ്ങളിലേക്ക് മാറ്റിക്കൊണ്ട് ഇഷ്ടാനുസൃത ഭാഷാ വിപുലീകരണങ്ങളോ ഡൊമെയ്ൻ-സ്പെസിഫിക് ഭാഷകളോ (DSLs) ഉണ്ടാക്കുക.
- സുരക്ഷാ ഓഡിറ്റിംഗ്: അപകടകരമായ കോഡ് ഘടനകളോ സുരക്ഷാ പ്രശ്നങ്ങളോ വിശകലനം ചെയ്യുക. സുരക്ഷിതമല്ലാത്ത കോഡിംഗ് രീതികൾ തിരിച്ചറിയാൻ ഇത് ഉപയോഗിക്കാം.
ഉദാഹരണം: കോഡിംഗ് ശൈലി നടപ്പിലാക്കുന്നു
നിങ്ങളുടെ പ്രോജക്റ്റിലെ എല്ലാ ഫംഗ്ഷൻ പേരുകളും snake_case കൺവെൻഷൻ (ഉദാഹരണത്തിന്, my_function
, myFunction
എന്നതിന് പകരം) പാലിക്കണമെന്ന് നിങ്ങൾ ആഗ്രഹിക്കുന്നുവെന്ന് കരുതുക. ലംഘനങ്ങൾ പരിശോധിക്കാൻ നിങ്ങൾക്ക് ast
മൊഡ്യൂൾ ഉപയോഗിക്കാം.
import ast
import re
class SnakeCaseChecker(ast.NodeVisitor):
def __init__(self):
self.errors = []
def visit_FunctionDef(self, node):
if not re.match(r'^[a-z]+(_[a-z]+)*$', node.name):
self.errors.append(f"Function name '{node.name}' does not follow snake_case convention")
def check_code(self, code):
ast_tree = ast.parse(code)
self.visit(ast_tree)
return self.errors
# Example usage
code = """
def myFunction(x):
return x * 2
def calculate_area(width, height):
return width * height
"""
ast_tree = ast.parse(code)
checker = SnakeCaseChecker()
errors = checker.check_code(code)
if errors:
for error in errors:
print(error)
else:
print("No style violations found")
ഈ കോഡ് ast.NodeVisitor
-ൽ നിന്ന് ഇൻഹെറിറ്റ് ചെയ്യുന്ന ഒരു SnakeCaseChecker
ക്ലാസ് നിർവചിക്കുന്നു. visit_FunctionDef
മെത്തേഡ് ഫംഗ്ഷൻ്റെ പേര് snake_case റെഗുലർ എക്സ്പ്രഷനുമായി പൊരുത്തപ്പെടുന്നുണ്ടോ എന്ന് പരിശോധിക്കുന്നു. ഇല്ലെങ്കിൽ, അത് errors
ലിസ്റ്റിലേക്ക് ഒരു പിശക് സന്ദേശം ചേർക്കുന്നു. check_code
മെത്തേഡ് കോഡ് പാർസ് ചെയ്യുകയും, AST-യിലൂടെ സഞ്ചരിക്കുകയും, പിശകുകളുടെ ലിസ്റ്റ് തിരികെ നൽകുകയും ചെയ്യുന്നു.
ast
മൊഡ്യൂൾ ഉപയോഗിക്കുമ്പോൾ ശ്രദ്ധിക്കേണ്ട കാര്യങ്ങൾ
- AST ഘടന മനസ്സിലാക്കുക: AST മാറ്റം വരുത്താൻ ശ്രമിക്കുന്നതിന് മുൻപ്,
ast.dump()
ഉപയോഗിച്ച് അതിൻ്റെ ഘടന മനസ്സിലാക്കാൻ സമയം കണ്ടെത്തുക. ഇത് നിങ്ങൾ പ്രവർത്തിക്കേണ്ട നോഡുകൾ തിരിച്ചറിയാൻ സഹായിക്കും. ast.NodeVisitor
ഉംast.NodeTransformer
ഉം ഉപയോഗിക്കുക: ഈ ക്ലാസുകൾ ട്രീയെ സ്വമേധയാ നാവിഗേറ്റ് ചെയ്യാതെ തന്നെ AST-യിലൂടെ സഞ്ചരിക്കാനും മാറ്റം വരുത്താനുമുള്ള സൗകര്യപ്രദമായ മാർഗ്ഗം നൽകുന്നു.- സമഗ്രമായി പരിശോധിക്കുക: AST മാറ്റം വരുത്തുമ്പോൾ, മാറ്റങ്ങൾ ശരിയാണെന്നും പിശകുകൾ വരുത്തുന്നില്ലെന്നും ഉറപ്പാക്കാൻ നിങ്ങളുടെ കോഡ് സമഗ്രമായി പരിശോധിക്കുക.
- കോഡ് ജനറേഷനായി
astunparse
പരിഗണിക്കുക: മാറ്റം വരുത്തിയ കോഡ് പ്രവർത്തിപ്പിക്കാൻcompile()
ഉപയോഗപ്രദമാണെങ്കിലും, ഒരു AST-യിൽ നിന്ന് വായിക്കാവുന്ന പൈത്തൺ കോഡ് ഉണ്ടാക്കാൻastunparse
ഒരു മാർഗ്ഗം നൽകുന്നു. - ടൈപ്പ് ഹിൻ്റുകൾ ഉപയോഗിക്കുക: ടൈപ്പ് ഹിൻ്റുകൾക്ക് നിങ്ങളുടെ കോഡിന്റെ വായിക്കാവുന്ന അവസ്ഥയും മെയിൻ്റയിൻ ചെയ്യാനുള്ള എളുപ്പവും ഗണ്യമായി മെച്ചപ്പെടുത്താൻ കഴിയും, പ്രത്യേകിച്ചും സങ്കീർണ്ണമായ AST ഘടനകളുമായി പ്രവർത്തിക്കുമ്പോൾ.
- നിങ്ങളുടെ കോഡ് രേഖപ്പെടുത്തുക: ഇഷ്ടാനുസൃത AST വിസിറ്റർമാരെയോ ട്രാൻസ്ഫോർമർമാരെയോ സൃഷ്ടിക്കുമ്പോൾ, ഓരോ മെത്തേഡിൻ്റെയും ഉദ്ദേശ്യവും AST-യിൽ അത് വരുത്തുന്ന മാറ്റങ്ങളും വ്യക്തമാക്കുന്നതിന് നിങ്ങളുടെ കോഡ് വ്യക്തമായി രേഖപ്പെടുത്തുക.
വെല്ലുവിളികളും പരിഗണനകളും
- സങ്കീർണ്ണത: AST-കളുമായി പ്രവർത്തിക്കുന്നത് സങ്കീർണ്ണമാണ്, പ്രത്യേകിച്ചും വലിയ കോഡ്ബേസുകളിൽ. വ്യത്യസ്ത നോഡ് തരങ്ങളെയും അവയുടെ ബന്ധങ്ങളെയും മനസ്സിലാക്കുന്നത് വെല്ലുവിളിയാകാം.
- പരിപാലനം: AST ഘടനകൾ പൈത്തൺ പതിപ്പുകൾക്കിടയിൽ മാറാം. അനുയോജ്യത ഉറപ്പാക്കാൻ നിങ്ങളുടെ കോഡ് വ്യത്യസ്ത പൈത്തൺ പതിപ്പുകൾക്കൊപ്പം പ്രവർത്തിക്കുന്നുണ്ടോയെന്ന് പരിശോധിക്കുക.
- പ്രവർത്തനക്ഷമത: വലിയ AST-കളിലൂടെ സഞ്ചരിക്കുന്നതും മാറ്റം വരുത്തുന്നതും വേഗത കുറഞ്ഞതായിരിക്കാം. പ്രവർത്തനക്ഷമത മെച്ചപ്പെടുത്തുന്നതിന് നിങ്ങളുടെ കോഡ് ഒപ്റ്റിമൈസ് ചെയ്യുന്നത് പരിഗണിക്കുക. പതിവായി ആക്സസ് ചെയ്യുന്ന നോഡുകൾ കാഷെ ചെയ്യുന്നതോ കൂടുതൽ കാര്യക്ഷമമായ അൽഗോരിതങ്ങൾ ഉപയോഗിക്കുന്നതോ സഹായിക്കും.
- പിശക് കൈകാര്യം ചെയ്യൽ: AST പാർസ് ചെയ്യുമ്പോഴോ മാറ്റം വരുത്തുമ്പോഴോ പിശകുകൾ ഭംഗിയായി കൈകാര്യം ചെയ്യുക. ഉപയോക്താവിന് വിവരങ്ങൾ നൽകുന്ന പിശക് സന്ദേശങ്ങൾ നൽകുക.
- സുരക്ഷ: ഒരു AST-യിൽ നിന്ന് ഉണ്ടാക്കിയ കോഡ് പ്രവർത്തിപ്പിക്കുമ്പോൾ ശ്രദ്ധിക്കുക, പ്രത്യേകിച്ചും AST ഉപയോക്തൃ ഇൻപുട്ടിനെ അടിസ്ഥാനമാക്കിയുള്ളതാണെങ്കിൽ. കോഡ് ഇൻജക്ഷൻ ആക്രമണങ്ങൾ തടയാൻ ഇൻപുട്ട് ശുദ്ധീകരിക്കുക.
പൈത്തൺ കോഡിന്റെ അബ്സ്ട്രാക്റ്റ് സിൻ്റാക്സ് ട്രീയുമായി സംവദിക്കാൻ പൈത്തൺ ast
മൊഡ്യൂൾ ശക്തവും വഴക്കമുള്ളതുമായ ഒരു മാർഗ്ഗം നൽകുന്നു. AST ഘടന മനസ്സിലാക്കുകയും ast.NodeVisitor
, ast.NodeTransformer
ക്ലാസുകൾ ഉപയോഗിക്കുകയും ചെയ്യുന്നതിലൂടെ, നിങ്ങൾക്ക് പൈത്തൺ കോഡ് പ്രോഗ്രാമാറ്റിക്കായി വിശകലനം ചെയ്യാനും, മാറ്റം വരുത്താനും, ഉണ്ടാക്കാനും കഴിയും. ഇത് കോഡ് വിശകലന ടൂളുകൾ മുതൽ ഓട്ടോമേറ്റഡ് റിഫാക്ടറിംഗ്, കസ്റ്റം ഭാഷാ വിപുലീകരണങ്ങൾ വരെ വൈവിധ്യമാർന്ന ആപ്ലിക്കേഷനുകളിലേക്ക് വഴിയൊരുക്കുന്നു. AST-കളുമായി പ്രവർത്തിക്കുന്നത് സങ്കീർണ്ണമാണെങ്കിലും, കോഡിനെ പ്രോഗ്രാമാറ്റിക്കായി കൈകാര്യം ചെയ്യാനുള്ള കഴിവുകൾക്ക് വലിയ പ്രയോജനങ്ങളുണ്ട്. നിങ്ങളുടെ പൈത്തൺ പ്രോജക്റ്റുകളിൽ പുതിയ സാധ്യതകൾ തുറക്കുന്നതിന് ast
മൊഡ്യൂളിന്റെ ശക്തി പ്രയോജനപ്പെടുത്തുക.