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 a
Puedo 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
foo
se 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 lalen
funció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.3
intérprete.import inspect
+inspect.getsource(foo)
funcionó bien.dis
es 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
inspect
es 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.getsource
fromdill
, 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.getsource
inspecciona el historial del intérprete en busca de funciones, clases, lambdas, etc., no inspecciona el contenido de las cadenas pasadas a exec.dill
para responder a esta pregunta: stackoverflow.com/questions/13827543/…dill.source
tiene funciones comogetname
yimportable
ygetsource
que se centran en obtener el código fuente (o un importable que produce el objeto) para cualquier objeto dado. Para cosas simples como unint
no 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.) Puededill
resolver 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
ipython
pero no es simplepython
. Sin embargo, debería estar bien en ambos al importar código de archivos fuente.fuente
getsource(foo)
.Puede usar el
inspect
módulo para obtener el código fuente completo para eso. Tienes que usar elgetsource()
método para eso desde elinspect
mó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-lambda
es más ligero y admite cualquier tipo de operación, pero solo funciona para una sola variableSymPy
es 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-lambda
documentació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
inspect
le 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