Comment puis-je obtenir le code source d'une fonction Python?

supposons que j'ai une fonction Python comme défini ci-dessous:

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

je peux obtenir le nom de la fonction en utilisant foo.func_name . Comment puis-je obtenir son code source par programmation, comme je l'ai tapé ci-dessus?

271
demandé sur Vertexwahn 2009-01-09 12:02:37

11 réponses

si la fonction est à partir d'un fichier source disponible sur le système de fichiers, alors inspect.getsource(foo) pourrait être utile:

si foo est défini comme:

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

puis:

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

Retourne:

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

mais je crois que si la fonction est compilée à partir d'une chaîne, d'un flux ou importée à partir d'un fichier compilé, alors vous ne pouvez pas récupérer son code source.

396
répondu Rafał Dowgird 2018-04-02 17:21:25

le inspecte module a des méthodes pour extraire le code source des objets python. Apparemment il ne fonctionne que si la source est située dans un fichier. Si vous aviez ça, vous n'auriez pas besoin d'obtenir la source de l'objet.

172
répondu runeh 2016-12-28 15:41:28

dis est votre ami si le code source n'est pas 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
71
répondu schlamar 2013-06-28 06:11:18

si vous utilisez IPython, vous devez taper " foo??"

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

File:      ~/Desktop/<ipython-input-18-3174e3126506>
Type:      function
50
répondu prashanth 2016-05-09 09:11:05

bien que je sois généralement d'accord que inspect est une bonne réponse, Je ne suis pas d'accord que vous ne pouvez pas obtenir le code source des objets définis dans l'interpréteur. Si vous utilisez dill.source.getsource de dill , vous pouvez obtenir la source des fonctions et lambdas, même si elles sont définies de manière interactive. Il peut également obtenir le code pour les méthodes et les fonctions de classe liées ou non définies dans curries... cependant, vous pourriez ne pas être en mesure de compiler ce code sans le englobante de l'objet du code.

>>> 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

>>> 
48
répondu Mike McKerns 2014-01-24 17:51:36

, Pour s'étendre sur runeh réponse:

>>> def foo(a):
...    x = 2
...    return x + a

>>> import inspect

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

print inspect.getsource(foo)
def foo(a):
   x = 2
   return x + a

éditer: comme souligné par @0sh cet exemple fonctionne en utilisant ipython mais pas simple python . Il devrait être bien dans les deux, cependant, lors de l'importation de code à partir de fichiers source.

20
répondu TomDotTom 2015-06-26 09:07:16

vous pouvez utiliser le module inspect pour obtenir le code source complet. Vous devez utiliser la méthode getsource() pour celle du module inspect . Par exemple:

import inspect

def get_my_code():
    x = "abcd"
    return x

print(inspect.getsource(get_my_code))

Vous pouvez le vérifier plus d'options sur le lien ci-dessous. récupérez votre code python

10
répondu Krutarth Gor 2017-07-31 11:47:29

si vous définissez strictement la fonction vous-même et que c'est une définition relativement courte, une solution sans dépendances serait de définir la fonction dans une chaîne de caractères et d'attribuer l'éval() de l'expression à votre fonction.

E. G.

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

ensuite éventuellement pour attacher le code original à la fonction:

func.source = funcstring
3
répondu cherplunk 2012-04-17 17:44:09

pour résumer:

import inspect
print( "".join(inspect.getsourcelines(foo)[0]))
2
répondu douardo 2017-01-03 17:35:42

veuillez noter que les réponses acceptées ne fonctionnent que si la lambda est indiquée sur une ligne séparée. Si vous le passez en argument à une fonction et souhaitez récupérer le code de la lambda comme objet, le problème devient un peu délicat puisque inspect vous donnera toute la ligne.

par exemple, considérez un fichier test.py :

import inspect

def main():
    x, f = 3, lambda a: a + 1
    print(inspect.getsource(f))

if __name__ == "__main__":
    main()

L'exécuter vous donne l'attention!):

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

à récupérer le code source de la lambda, votre meilleur pari, à mon avis, est de re-analyser l'ensemble du fichier source (en utilisant f.__code__.co_filename ) et de faire correspondre le noeud lambda AST par le numéro de ligne et son contexte.

nous avons dû faire précisément que dans notre bibliothèque de conception-par-contrat icontract depuis que nous avons dû Parser les fonctions lambda nous passons en tant qu'arguments aux décorateurs. Il est trop de code à coller ici, alors jetez un oeil à la mise en œuvre de cette fonction .

0
répondu marko.ristin 2018-09-14 14:07:27

je croire que les noms de variables ne sont pas stockées dans pyc/pyd/pyo fichiers, de sorte que vous ne pouvez pas récupérer le code exact de lignes si vous n'avez pas les fichiers source.

-2
répondu Abgan 2009-01-09 09:38:47