Comment exécuter une chaîne contenant du code Python en Python?

comment exécuter une chaîne contenant du code Python en Python?

252
demandé sur SilentGhost 2009-03-31 20:12:20

12 réponses

pour les déclarations, utiliser exec(string) (Python 2/3) ou exec string (Python 2):

>>> mycode = 'print "hello world"'
>>> exec(mycode)
Hello world

lorsque vous avez besoin de la valeur d'une expression, utilisez eval(string) :

>>> x = eval("2+2")
>>> x
4

Toutefois, la première étape devrait être de vous demander si vous avez vraiment besoin. L'exécution de code devrait généralement être la position de dernier recours: il est lent, laid et dangereux si elle peut contenir saisies par l'utilisateur code. Vous devriez toujours chercher d'autres solutions, par exemple des fonctions d'ordre supérieur, pour voir si elles peuvent mieux répondre à vos besoins.

246
répondu Brian 2016-09-16 08:22:07

dans l'exemple, une chaîne de caractères est exécutée en code à l'aide de la fonction exec.

import sys
import StringIO

# create file-like string to capture output
codeOut = StringIO.StringIO()
codeErr = StringIO.StringIO()

code = """
def f(x):
    x = x + 1
    return x

print 'This is my output.'
"""

# capture output and errors
sys.stdout = codeOut
sys.stderr = codeErr

exec code

# restore stdout and stderr
sys.stdout = sys.__stdout__
sys.stderr = sys.__stderr__

print f(4)

s = codeErr.getvalue()

print "error:\n%s\n" % s

s = codeOut.getvalue()

print "output:\n%s" % s

codeOut.close()
codeErr.close()
54
répondu hekevintran 2009-03-31 16:14:38

rappelez-vous que de la version 3 exec est une fonction!

donc toujours utiliser exec(mystring) au lieu de exec mystring .

19
répondu bheks 2015-12-11 02:12:50

eval et exec sont la bonne solution, et ils peuvent être utilisés dans un plus sûr .

comme discuté dans manuel de référence de Python et clairement expliqué dans ce" tutoriel , les fonctions eval et exec prennent deux paramètres supplémentaires qui permettent à un utilisateur de spécifier quelles fonctions et variables globales et locales sont disponibles.

pour exemple:

public_variable = 10

private_variable = 2

def public_function():
    return "public information"

def private_function():
    return "super sensitive information"

# make a list of safe functions
safe_list = ['public_variable', 'public_function']
safe_dict = dict([ (k, locals().get(k, None)) for k in safe_list ])
# add any needed builtins back in
safe_dict['len'] = len

>>> eval("public_variable+2", {"__builtins__" : None }, safe_dict)
12

>>> eval("private_variable+2", {"__builtins__" : None }, safe_dict)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1, in <module>
NameError: name 'private_variable' is not defined

>>> exec("print \"'%s' has %i characters\" % (public_function(), len(public_function()))", {"__builtins__" : None}, safe_dict)
'public information' has 18 characters

>>> exec("print \"'%s' has %i characters\" % (private_function(), len(private_function()))", {"__builtins__" : None}, safe_dict)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1, in <module>
NameError: name 'private_function' is not defined

en substance, vous définissez l'espace de noms dans lequel le code sera exécuté.

18
répondu alan 2017-06-30 18:28:58

eval() est juste pour les expressions, tandis que eval('x+1') fonctionne, eval('x=1') ne fonctionnera pas par exemple. Dans ce cas, il est préférable d'utiliser exec , ou encore mieux: essayer de trouver une meilleure solution:)

11
répondu LGB 2011-09-12 19:32:25

vous exécutez le code en utilisant exec, comme avec la session de ralenti suivante:

>>> kw = {}
>>> exec( "ret = 4" ) in kw
>>> kw['ret']

4
9
répondu gus 2012-07-18 22:55:50

éviter exec et eval

utilisant exec et eval en Python est très mal vu.

Il existe de meilleures alternatives

à Partir du haut de réponse (l'emphase est mienne):

pour les mentions, utiliser exec .

si vous avez besoin de la valeur d'une expression, utilisez eval .

cependant, le première étape devrait être de vous demander si vous avez vraiment besoin. le code D'exécution devrait généralement être la position de dernier recours : il est lent, laid et dangereux s'il peut contenir le code entré par l'utilisateur. Vous devriez toujours regarder les alternatives d'abord , telles que les fonctions d'ordre plus élevé , pour voir si ceux-ci peuvent mieux répondre à vos besoins.

à Partir de solutions de rechange " exec/eval?

définir et obtenir des valeurs de variables avec les noms dans les chaînes de caractères

[tandis que eval ] fonctionnerait, il n'est généralement pas conseillé d'utiliser des noms de variables portant un sens au programme lui-même.

utilisez plutôt un dict.

Il n'est pas idiomatique

de http://lucumr.pocoo.org/2011/2/1/exec-in-python / (souligné par moi))

Python n'est pas PHP

N'essayez pas de contourner les idiomes de Python parce qu'un autre langage le fait différemment. Namespaces sont en Python pour une raison et juste parce qu'il vous donne l'outil exec cela ne signifie pas que vous devez utiliser cet outil.

C'est dangereux

de http://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html (l'emphase est mienne)

donc eval n'est pas sûr, même si vous retirez tous les globals et les builtins!

le problème avec tous ces tentatives pour protéger eval() est qu'ils sont des listes noires . Ils explicitement supprimer des choses qui pourraient être dangereuses. C'est une bataille perdue d'avance car s'il ne reste qu'un seul article la liste, vous pouvez attaquer le système .

alors, eval peut-il être sécurisé? Dur à dire. À ce stade, ma meilleure supposition est que vous ne pouvez pas faire de mal si vous ne pouvez pas utiliser de double underscores, donc peut-être que si vous excluez une chaîne avec double underscores, vous êtes en sécurité. Peut-être...

il est difficile de lire et de comprendre

de http://stupidpythonideas.blogspot.it/2013/05/why-evalexec-is-bad.html (l'emphase est mienne):

D'abord, exec rend plus difficile pour les êtres humains de lire votre code . Pour comprendre ce qui se passe, Je ne dois pas seulement lire votre code, je dois lire votre code, comprendre quelle chaîne de caractères il va générer, puis lire ce code virtuel. donc, si vous travaillez sur une équipe, ou publier un logiciel libre, ou demander de l'aide dans un endroit comme StackOverflow, ça rend plus difficile pour les autres de vous aider. Et s'il y a une chance que vous débuggiez ou développiez ce code dans 6 mois, vous rendez les choses plus difficiles pour vous-même directement.

8
répondu Caridorc 2017-05-23 12:18:15

Check out eval :

x = 1
print eval('x+1')
->2
3
répondu ryeguy 2009-03-31 16:14:05

la solution la plus logique serait d'utiliser la fonction intégrée eval () .Une autre solution est d'écrire la chaîne temporaire python fichier et de l'exécuter.

3
répondu John T 2009-03-31 16:15:10

Utiliser eval .

1
répondu Pablo Santa Cruz 2009-03-31 16:13:49

Ok .. Je sais que ce n'est pas vraiment une réponse, mais peut-être une note pour les gens qui regardent ça comme je l'étais. Je voulais exécuter du code spécifique pour différents utilisateurs / clients mais aussi éviter l'exec / eval. J'ai d'abord cherché à stocker le code dans une base de données pour chaque utilisateur et faire ce qui précède.

j'ai fini par créer les fichiers sur le système de fichiers dans un dossier' customer_filters 'et en utilisant le module' imp', si aucun filtre n'est appliqué pour ce client, il suffit

import imp


def get_customer_module(customerName='default', name='filter'):
    lm = None
    try:
        module_name = customerName+"_"+name;
        m = imp.find_module(module_name, ['customer_filters'])
        lm = imp.load_module(module_name, m[0], m[1], m[2])
    except:
        ''
        #ignore, if no module is found, 
    return lm

m = get_customer_module(customerName, "filter")
if m is not None:
    m.apply_address_filter(myobj)

donc, nomclient = "jj" exécuterait apply_address_filter à partir du customer_filters\jj_filter.py dossier

0
répondu Brian 2017-04-12 13:00:15

cela vaut la peine de mentionner, que le frère de exec existe aussi bien appelé execfile si vous voulez appeler un fichier python. Cela est parfois bon si vous travaillez dans un paquet tiers qui ont terrible IDE inclus et vous voulez coder en dehors de leur paquet.

exemple:

execfile('/path/to/source.py)'

ou:

exec(open("/path/to/source.py").read())

0
répondu user1767754 2018-01-02 00:42:18