8
votes

Utilisation d'EXEC et EVAL dans Python

J'ai donc compris ce que exécu et eval et aussi compile faire. Mais pourquoi aurais-je besoin de les utiliser? Je suis peu clair sur le scénario d'utilisation.

Quelqu'un peut-il me donner quelques exemples afin que je puisse mieux apprécier le concept. Parce que je sais que c'est toute la théorie.


3 commentaires

Fait: des choses comme eval sont très rarement un choix valide, et uniquement si la chaîne a été utilisée pour qu'elle soit sécurisée.


Essayez d'obtenir dans les fichiers de code source Python dans la bibliothèque Standard Python. C'est toujours un endroit intéressant pour commencer si vous souhaitez voir des fonctionnalités de base python utilisées bien.


EXEC et eval peut être assez utile dans CodeGolfing .


8 Réponses :


0
votes

Vous demandez simplement un exemple? Vous pouvez écrire une application simple qui lit de la norme dans et permet à l'utilisateur de saisir diverses expressions, telles que (4 * 2) / 8 - 1 . Dans d'autres langues (Java, C ++, etc.), il serait proche de l'impossible à évaluer, mais en Python, il est simple, juste: xxx

qui étant dit, à moins que vous soyez prudent, en utilisant Ces choses peuvent être très dangereuses car elles (essentiellement) permettent à l'utilisateur une énorme quantité d'accès.


2 commentaires

Non "près de l'impossibilité d'évaluer" --- Python lui-même est écrit principalement dans C et Python peut évaluer de telles expressions. Mieux vaut dire que l'évaluation des expressions impliquerait autant de travail que d'écrire un analyseur et un compilateur de langues de programmation.


@Jim Dennis. Convenu que ce n'est pas "proche de l'impossible". C'est faisable à quelques heures, peut-être encore moins. Mais c'est une douleur.



0
votes

Ceci est utilisé dans la méta-programmation (lorsque le programme se écrit). Par exemple, vous avez des animaux de différentes espèces, qui sont décrits avec différentes classes: lion, tigre, cheval, âne. Et vous voulez simuler un croisement entre eux, pour ex-exampe, entre Lion et Tiger. Lorsque vous écrivez le programme, vous ne pouvez pas déterminer comment l'utilisateur traversera les animaux, mais vous pouvez créer de nouvelles classes d'animaux à la volée:

new_class_name = boy.class.to_str() + girl.class.to_str()
eval("class " + new_class_name + " extends " + boy.class.to_str() + ", " + girl.class.to_str())


1 commentaires

Non, ce n'est pas une utilisation valide de eval - Vous devez utiliser type à la place.



2
votes

vous n'a pas besoin pour les utiliser et à mon avis, vous devriez les éviter.

Ils ne sont utiles que dans les cas où vous générez le code lui-même, ce qui sera très probablement considéré comme une mauvaise pratique.

Si vous envisagez d'utiliser Eval () pour des choses comme des expressions mathématiques, vous feriez mieux assainir l'entrée avant de l'évaluer. Vous ne savez jamais quel type de "texte" l'utilisateur envoie en ce qui pourrait bousculer l'application elle-même.


5 commentaires

Avoir une "méta-programmation" égale à la "mauvaise pratique" est un peu dur, imho. Une méta-programmation, tandis parfois plus complexe et plus sujette d'erreur, peut donner un code meilleur (c'est-à-dire plus rapide ou plus maintenu) lorsqu'il est utilisé correctement.


La méta-programmation n'est pas une mauvaise pratique. Ça peut être très beau.


Chaque outil et méthode a son domaine d'application. Mais vous avez raison, le domaine d'application de la méta-programmation est très étroit.


@Paulo - Belle ne devrait jamais être la raison d'écrire du bon code. @Kos - Je faisais référence principalement à l'exécutif et à compiler ... comme l'auteur de la question mentionnée, je n'ai jamais vu de bons cas d'utilisation où ils ne pouvaient pas être réécrites de manière plus simple ou moins élaborée. En outre, la méta-programmation peut être obtenue sans utiliser ces 3 mots-clés


Un moyen différent de dire que cela pourrait être "Si vous avez besoin de demander, vous devriez probablement les éviter." Bien que vous puissiez parfois obtenir des solutions très élégantes aux problèmes, de nombreuses solutions sont plus difficiles à comprendre, difficiles à prolonger et difficiles à déboguer.



4
votes

La bibliothèque standard a un exemple instructif d'utiliser EXEC code>. Collections.NamedTutuple l'utilise pour construire une classe de manière dynamique.

template = '''class %(typename)s(tuple):
    '%(typename)s(%(argtxt)s)' \n
    __slots__ = () \n
    _fields = %(field_names)r \n
    def __new__(_cls, %(argtxt)s):
        'Create new instance of %(typename)s(%(argtxt)s)'
        return _tuple.__new__(_cls, (%(argtxt)s)) \n
    ...'''

   namespace = dict(_itemgetter=_itemgetter, __name__='namedtuple_%s' % typename,
                     OrderedDict=OrderedDict, _property=property, _tuple=tuple)
   try:
       exec template in namespace
   except SyntaxError, e:
       raise SyntaxError(e.message + ':\n' + template)


3 commentaires

@Dan_waterworth: Oups, désolé d'avoir supprimé mon commentaire (je n'avais pas vu le vôtre). Oui, je suis d'accord que c'est possible.


@Dan_waterworth: J'aimerais savoir que Raymond Hettinger a choisi de le mettre en œuvre avec EXEC au lieu d'une métaclasse.


@unutbu dans un numéro de 2008 que je viens de courir dans l'endroit où quelqu'un a offert une version non-Eval, Raymond et un autre développeur pèsent sur les problèmes avec les premières expériences de non-évaluation nommé tuples: bugs.python.org/issue3974



3
votes

ast code> utilise compiler code> pour générer des arbres de syntaxe abstrait à partir de code source Python. Ceux-ci sont utilisés par des modules tels que pyflakes code> pour analyser et valider Python.

def parse(expr, filename='<unknown>', mode='exec'):
    """
    Parse an expression into an AST node.
    Equivalent to compile(expr, filename, mode, PyCF_ONLY_AST).
    """
    return compile(expr, filename, mode, PyCF_ONLY_AST)


0 commentaires

0
votes

Voici un cas d'utilisation valide. Dans le middleware Python Pâte (pour la programmation Web) Lorsqu'une exception est soulevée, elle crée une ligne de commande dans le navigateur. Ces œuvres utilisent des méthodes comme celles-ci. En outre, dans Blender, il existe une option pour animer des valeurs à l'aide des expressions Python et ces travaux en utilisant EVAL.


0 commentaires

5
votes

Je vais donner un exemple dans lequel j'ai utilisé eval et où je pense que c'était le meilleur choix.

J'écris un simple utilitaire de test logiciel ... quelque chose à tester si les exercices d'étudiants se conformaient aux exigences de cession. L'objectif était de fournir un moyen de fournir un simple fichier de configuration de servir de spécification de test (pour contourner un problème de "poulet-œuf" d'utiliser un langage de programmation pour décrire / documenter / mettre en œuvre les cas de test pour les assignations de programmation élémentaire) .

i basé mon harnais sur la configuration dans les bibliothèques standard. Cependant, je voulais que la capacité de représenter des chaînes de python arbitraires (y compris des interpolations de \ n, \ t, et en particulier de tout personnage ASCII codé hex-hex interpoléré dans les valeurs, lues à partir de celle-ci.

Ma solution était un Essayez autour d'un parsed_string = eval (''% s ''% cfg_read_item) suivi d'un Essayez de la version triple double-cited ("" "% s" "") de la même manière.

Ceci est un cas où l'alternative aurait été d'écrire (ou de trouver un analyseur de langue python pré-écrit) et de déterminer comment inclure et l'adapter à mon programme. Les risques sont minimes (je ne suis pas inquiété que le code soumis par l'étudiant achemine mon analyseur, rompre si sa prison, supprimez tous mes fichiers, envoyez mes numéros de carte de crédit à la Roumanie, etc.) *

* (en partie parce que je les testais sous Linux à partir d'un compte d'utilisateur sans tête non approuvé).

Comme ici d'autres, il existe d'autres cas d'utilisation dans lesquels vous construisez un code d'un modèle en fonction des données d'entrée et de l'exécution de ce code (méta-programmation). Vous devriez toujours être capable d'accomplir ces tâches d'une autre manière. Cependant, chaque fois que cette alternative implique un effort de codage qui s'approche de l'écriture d'un analyseur / compilateur / interpréteur de langue de programmation générale .... alors eval peut être la meilleure approche.


0 commentaires

1
votes

Je pense avoir une utilisation valide. J'utilise Python 3.2.1 Intérieur Blender 2.6.4 Pour modifier un ensemble de points avec X, Y coordonnées Y (dans le plan Z).

L'objectif est d'ajouter des anneaux concentriques de nouveaux points autour de chaque point existant, avec les bagues qui se comportent comme des ondulations (comme lorsque vous laissez tomber une pierre dans un étang). La capture est que je veux que les ondulations soient interfèrer de manière constructive / destructive entre elles, alors je traverse et construisez une «équation d'ondulation» centrée à chaque point et résume toutes les équations d'ondulation dans une équation mathématique gigantesque, qui Je vais ensuite nourrir les points d'origine dans afin de générer la valeur z correcte pour assigner chacun à.

Mon plan consiste à ajouter chaque terme supplémentaire dans l'équation à la précédente en tant que chaîne, puis utilisez Eval () pour calculer la valeur Z de la nouvelle série de points.


0 commentaires