Supongamos que tengo una función de Python como se define a continuación:
def foo(arg1,arg2):
    #do something with args
    a = arg1 + arg2
    return aPuedo obtener el nombre de la función usando foo.func_name. ¿Cómo puedo obtener programáticamente su código fuente, como escribí anteriormente?

foo.__name__Respuestas:
Si la función es de un archivo fuente disponible en el sistema de archivos, entonces
inspect.getsource(foo)podría ser de ayuda:Si
foose define como:Entonces:
Devoluciones:
Pero creo que si la función se compila desde una cadena, secuencia o se importa desde un archivo compilado, entonces no puede recuperar su código fuente.
fuente
len. ¿Dónde puedo encontrar el código fuente de lalenfunción?inspect.getsourcelines(foo)El módulo de inspección tiene métodos para recuperar el código fuente de los objetos python. Aparentemente, solo funciona si la fuente se encuentra en un archivo. Si tuviera eso, supongo que no necesitaría obtener la fuente del objeto.
fuente
python 3.5.3intérprete.import inspect+inspect.getsource(foo)funcionó bien.dises tu amigo si el código fuente no está disponible:fuente
Si está utilizando IPython, entonces debe escribir "foo ??"
fuente
dir(MyClass), a continuación,MyClass.__init__??y así sucesivamente.Aunque generalmente estoy de acuerdo con que
inspectes una buena respuesta, no estoy de acuerdo con que no pueda obtener el código fuente de los objetos definidos en el intérprete. Si usadill.source.getsourcefromdill, puede obtener la fuente de funciones y lambdas, incluso si se definen de forma interactiva. También puede obtener el código de los métodos y funciones de clase vinculados o no definidos definidos en curry ... sin embargo, es posible que no pueda compilar ese código sin el código del objeto adjunto.fuente
dill.source.getsourceinspecciona el historial del intérprete en busca de funciones, clases, lambdas, etc., no inspecciona el contenido de las cadenas pasadas a exec.dillpara responder a esta pregunta: stackoverflow.com/questions/13827543/…dill.sourcetiene funciones comogetnameyimportableygetsourceque se centran en obtener el código fuente (o un importable que produce el objeto) para cualquier objeto dado. Para cosas simples como unintno hay fuente, por lo que no funciona como se esperaba (es decir, para 'a = 10' devuelve '10').>>> a = 10; print( [key for key, val in globals().items() if val is a][0] )dill, pero mi respuesta deja un poco que desear (es decir, si tiene varios nombres para el mismo valor, no puede averiguar cuál se usó). pasar una expresión, no puede decir cuál era esa expresión. Demonios, si pasa una expresión que se evalúa igual que un nombre, en su lugar le dará ese nombre.) Puededillresolver cualquiera de esas deficiencias de mi respuesta aquí: stackoverflow.com/a/28634996/901641Para ampliar la respuesta de runeh:
EDITAR: Como lo señaló @ 0sh, este ejemplo funciona usando
ipythonpero no es simplepython. Sin embargo, debería estar bien en ambos al importar código de archivos fuente.fuente
getsource(foo).Puede usar el
inspectmódulo para obtener el código fuente completo para eso. Tienes que usar elgetsource()método para eso desde elinspectmódulo. Por ejemplo:Puede consultar más opciones en el siguiente enlace. recupera tu código de Python
fuente
Como esta publicación está marcada como el duplicado de esta otra publicación , respondo aquí para el caso "lambda", aunque el OP no se trata de lambdas.
Entonces, para las funciones lambda que no están definidas en sus propias líneas: además de la respuesta de marko.ristin , es posible que desee usar mini-lambda o SymPy como se sugiere en esta respuesta .
mini-lambdaes más ligero y admite cualquier tipo de operación, pero solo funciona para una sola variableSymPyes más pesado pero está mucho más equipado con operaciones matemáticas / de cálculo. En particular, puede simplificar sus expresiones. También admite varias variables en la misma expresión.Así es como puedes hacerlo usando
mini-lambda:Produce correctamente
Consulte la
mini-lambdadocumentación para más detalles. Soy el autor por cierto;)fuente
Tenga en cuenta que las respuestas aceptadas funcionan solo si la lambda se proporciona en una línea separada. Si lo pasa como argumento a una función y desea recuperar el código de lambda como objeto, el problema se vuelve un poco complicado ya que
inspectle dará toda la línea.Por ejemplo, considere un archivo
test.py:Ejecutarlo te da (¡cuidado con la sangría!):
Para recuperar el código fuente de la lambda, su mejor opción, en mi opinión, es volver a analizar todo el archivo fuente (usando
f.__code__.co_filename) y hacer coincidir el nodo AST lambda por el número de línea y su contexto.Tuvimos que hacer precisamente eso en nuestro resumen de iconos de la biblioteca de diseño por contrato ya que tuvimos que analizar las funciones lambda que pasamos como argumentos a los decoradores. Es demasiado código para pegar aquí, así que eche un vistazo a la implementación de esta función .
fuente
Si está definiendo estrictamente la función usted mismo y es una definición relativamente corta, una solución sin dependencias sería definir la función en una cadena y asignar el eval () de la expresión a su función.
P.ej
luego, opcionalmente, para adjuntar el código original a la función:
fuente
para resumir :
fuente
Yo creo que los nombres de variables no se almacenan en archivos pyc / pyd / pyo, por lo que no puede recuperar las líneas de código exacto si usted no tiene los archivos de origen.
fuente