¿Cómo puedo obtener el código fuente de una función de Python?

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 su código fuente mediante progtwigción, como escribí anteriormente?

Si la función es de un archivo fuente disponible en el sistema de archivos, inspect.getsource(foo) podría ser de ayuda:

Si foo se define como:

 def foo(arg1,arg2): #do something with args a = arg1 + arg2 return a 

Entonces:

 import inspect lines = inspect.getsource(foo) print(lines) 

Devoluciones:

 def foo(arg1,arg2): #do something with args a = arg1 + arg2 return a 

Pero creo que si la función se comstack desde una cadena, secuencia o se importa desde un archivo comstackdo, entonces no puede recuperar su código fuente.

El módulo de inspección tiene métodos para recuperar el código fuente de los objetos de Python. Al parecer, solo funciona si la fuente se encuentra en un archivo sin embargo. Si tuvieras eso, supongo que no necesitarías obtener la fuente del objeto.

dis es tu amigo si el código fuente no está disponible:

 >>> import dis >>> def foo(arg1,arg2): ... #do something with args ... a = arg1 + arg2 ... return a ... >>> dis.dis(foo) 3 0 LOAD_FAST 0 (arg1) 3 LOAD_FAST 1 (arg2) 6 BINARY_ADD 7 STORE_FAST 2 (a) 4 10 LOAD_FAST 2 (a) 13 RETURN_VALUE 

Si está utilizando IPython, debe escribir “foo ??”

 In [19]: foo?? Signature: foo(arg1, arg2) Source: def foo(arg1,arg2): #do something with args a = arg1 + arg2 return a File: ~/Desktop/ Type: function 

Aunque en general estoy de acuerdo en que inspect es una buena respuesta, no estoy de acuerdo en que no pueda obtener el código fuente de los objetos definidos en el intérprete. Si usa dill.source.getsource de dill , puede obtener la fuente de funciones y lambdas, incluso si están definidas de manera interactiva. También puede obtener el código para los métodos y funciones de clase enlazados o no enlazados definidos en curries … sin embargo, es posible que no pueda comstackr ese código sin el código del objeto que lo contiene.

 >>> from dill.source import getsource >>> >>> def add(x,y): ... return x+y ... >>> squared = lambda x:x**2 >>> >>> print getsource(add) def add(x,y): return x+y >>> print getsource(squared) squared = lambda x:x**2 >>> >>> class Foo(object): ... def bar(self, x): ... return x*x+x ... >>> f = Foo() >>> >>> print getsource(f.bar) def bar(self, x): return x*x+x >>> 

Para ampliar la respuesta de runeh:

 >>> def foo(a): ... x = 2 ... return x + a >>> import inspect >>> inspect.getsource(foo) u'def foo(a):\nx = 2\n return x + a\n' print inspect.getsource(foo) def foo(a): x = 2 return x + a 

EDITAR: Como lo señaló @ 0sh, este ejemplo funciona con ipython pero no con python simple. Sin embargo, debería estar bien en ambos, al importar código de archivos de origen.

Puede usar el módulo de inspect para obtener el código fuente completo para eso. Tienes que usar el método getsource() para eso desde el módulo de inspect . Por ejemplo:

 import inspect def get_my_code(): x = "abcd" return x print(inspect.getsource(get_my_code)) 

Puedes ver más opciones en el siguiente enlace. recupera tu código python

para resumir :

 import inspect print( "".join(inspect.getsourcelines(foo)[0])) 

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 la eval () de la expresión a su función.

P.ej

 funcstring = 'lambda x: x> 5' func = eval(funcstring) 

luego, opcionalmente, para adjuntar el código original a la función:

 func.source = funcstring 

Tenga en cuenta que las respuestas aceptadas solo funcionan si la lambda se da en una línea separada. Si lo pasa como un argumento a una función y desea recuperar el código de la 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 :

 import inspect def main(): x, f = 3, lambda a: a + 1 print(inspect.getsource(f)) if __name__ == "__main__": main() 

Ejecutarlo te da (¡cuidado!):

  x, f = 3, lambda a: a + 1 

Para recuperar el código fuente de la lambda, su mejor apuesta, en mi opinión, es volver a analizar todo el archivo fuente (utilizando el 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 nuestra 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 .

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 exactas si no tiene archivos de origen.

Si usas IPython, otra opción es usar ?? Después del nombre de la función para ver su código fuente. Aquí hay un ejemplo:

 [nav] In [1]: def foo(arg1,arg2): ...: #do something with args ...: a = arg1 + arg2 ...: return a [nav] In [2]: foo?? Signature: foo(arg1, arg2) Docstring:  Source: def foo(arg1,arg2): #do something with args a = arg1 + arg2 return a