Para completarlo, me gustaría señalar que a veces es posible que desee código de análisis lugar de importarlo. Un import
va a ejecutar expresiones de nivel superior, y eso podría ser un problema.
Por ejemplo, estoy dejando que los usuarios seleccionen funciones de punto de entrada para paquetes hechos con zipapp. El uso de import
y inspect
arriesga la ejecución de un código erróneo, lo que provoca bloqueos, mensajes de ayuda impresos, ventanas emergentes de GUI, etc.
En lugar de eso usar el módulo ast para enumerar todas las funciones de nivel superior:
import ast
import sys
def top_level_functions(body):
return (f for f in body if isinstance(f, ast.FunctionDef))
def parse_ast(filename):
with open(filename, "rt") as file:
return ast.parse(file.read(), filename=filename)
if __name__ == "__main__":
for filename in sys.argv[1:]:
print(filename)
tree = parse_ast(filename)
for func in top_level_functions(tree.body):
print(" %s" % func.name)
Poner este código en list.py
y utilizando como entrada, me sale:
$ python list.py list.py
list.py
top_level_functions
parse_ast
Por supuesto, Navegar por un AST puede ser complicado algunas veces, incluso para un lenguaje relativamente simple como Python, porque el AST es bastante bajo. Pero si tiene un caso de uso simple y claro, es posible y seguro.
Sin embargo, un inconveniente es que no puede detectar las funciones que se generan en el tiempo de ejecución, como foo = lambda x,y: x*y
.
considere la posibilidad de revisar la respuesta seleccionada! hay soluciones mejores/más fáciles de usar que se sugieren en otras respuestas. – r2d2oid