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?
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.
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.
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
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
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
>>>
, 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.
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
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
pour résumer:
import inspect
print( "".join(inspect.getsourcelines(foo)[0]))
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 .
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.