¿Por qué usar 'eval' es una mala práctica?

Resuelto Nikwin asked hace 14 años • 8 respuestas

Utilizo la siguiente clase para almacenar fácilmente datos de mis canciones.

class Song:
    """The class to store the details of each song"""
    attsToStore=('Name', 'Artist', 'Album', 'Genre', 'Location')
    def __init__(self):
        for att in self.attsToStore:
            exec 'self.%s=None'%(att.lower()) in locals()
    def setDetail(self, key, val):
        if key in self.attsToStore:
            exec 'self.%s=val'%(key.lower()) in locals()

Siento que esto es mucho más extensible que escribir un if/elsebloque. Sin embargo, he oído que eso evalno es seguro. ¿Lo es? ¿Cual es el riesgo? ¿Cómo puedo resolver el problema subyacente en mi clase (establecer atributos selfdinámicamente) sin incurrir en ese riesgo?

Nikwin avatar Dec 02 '09 20:12 Nikwin
Aceptado

Sí, usarlo evales una mala práctica. Sólo por nombrar algunas razones:

  1. Casi siempre hay una mejor manera de hacerlo.
  2. Muy peligroso e inseguro.
  3. Dificulta la depuración
  4. Lento

En tu caso puedes usar setattr en su lugar:

class Song:
    """The class to store the details of each song"""
    attsToStore=('Name', 'Artist', 'Album', 'Genre', 'Location')
    def __init__(self):
        for att in self.attsToStore:
            setattr(self, att.lower(), None)
    def setDetail(self, key, val):
        if key in self.attsToStore:
            setattr(self, key.lower(), val)

Hay algunos casos en los que tienes que usar evalo exec. Pero son raros. Usar evalen su caso es una mala práctica con seguridad. Hago hincapié en las malas prácticas porque evaly execcon frecuencia se utilizan en el lugar equivocado.

Respondiendo a los comentarios:

Parece que algunos no están de acuerdo en que evalel caso OP sea "muy peligroso e inseguro". Esto podría ser cierto para este caso específico, pero no en general. La pregunta era general y las razones que enumeré también son válidas para el caso general.

Nadia Alramli avatar Dec 02 '2009 13:12 Nadia Alramli

El uso evales débil, no es una mala práctica claramente.

  1. Viola el "Principio Fundamental del Software". Su fuente no es la suma total de lo ejecutable. Además de su fuente, están los argumentos eval, que deben entenderse claramente. Por este motivo, es la herramienta de último recurso.

  2. Suele ser una señal de diseño irreflexivo. Rara vez hay una buena razón para el código fuente dinámico, creado sobre la marcha. Casi cualquier cosa se puede hacer con delegación y otras técnicas de diseño OO.

  3. Conduce a una compilación sobre la marcha relativamente lenta de pequeños fragmentos de código. Una sobrecarga que se puede evitar utilizando mejores patrones de diseño.

Como nota a pie de página, en manos de sociópatas trastornados, puede que no funcione bien. Sin embargo, cuando nos enfrentamos a usuarios o administradores sociópatas trastornados, es mejor no darles Python interpretado en primer lugar. En manos de los verdaderamente malvados, Python puede ser un riesgo; evalno aumenta el riesgo en absoluto.

S.Lott avatar Dec 02 '2009 18:12 S.Lott