[pyar] Uso eval() para clase definida en otro archivo

Juan Pablo Hernández Vogt jphv.mail en gmail.com
Vie Mar 3 16:53:57 ART 2017


Si Carlos, está usando el entorno del archivo base.py

Este concepto de entorno es nuevo para mi, que en otros lenguajes no está
presente de esta manera.

Finalmente puedo decir que hice un arreglo bastante simple gracias a que
todas las clases del archivo derived.py heredan de una clase común --> los
herederos setean el entorno que debe usarse.

Nota: no utilizo herencia múltiple.

Paso a documentar cómo se resolvió el caso:

*File: base.py*
class BaseObject(object):
    def __init__(self, parameters=None):
        self.parameters = parameters

        # Derived classes from other files must set its environment
        # in order to be able to execute eval() correctly.
        self.globals = None

    def load_parameter(self, key, value):
        if not self.parameters:
            self.parameters = {}

        self.parameters[key] = eval(value, self.globals)


*File: derived.py*
from base import *

# Using aenum from: pip install aenum
from aenum import Enum

class CalculationMode(Enum):
    Pass_2D = 0
    Pass_3D = 1


class Derived(BaseObject):
    def __init__(self, parameters=None):
        super(Derived, self).__init__(parameters)
        self.globals = globals()


class Child(Derived):
    def __init__(self, parameters=None):
        super(Child, self).__init__(parameters)


if __name__ == "__main__":

    obj = Child()

    obj.load_parameter('GENERIC_NAME', '"dummy"')
    obj.load_parameter('AMBIENT_TEMPERATURE', '293')
    obj.load_parameter('PRESSURE', '1013.25')
    obj.load_parameter('DUMMY', 'True')
    obj.load_parameter('passes', '[-1, 0, -1, 0]')

    print(obj.parameters)

    print("load enumeration")
    obj.load_parameter('MODE', 'CalculationMode.Pass_3D')
    print(obj.parameters)


Gracias por dale una mirada a este caso.

Saludos!

El 3 de marzo de 2017, 13:56, Carlos Matías <cmdelatorre en gmail.com>
escribió:

> Fijate si no te queda clara la doc de eval https://docs.python.org/3/
> library/functions.html#eval
>
> ...If both dictionaries are omitted [globals and locals], the expression
>> is executed in the environment where eval() is called.
>>
>
> Entonces me parece que se está usando el entorno del archivo *base.py*,
> en el que no está definido CalculationMode.
>
> ¿Puede ser?
>
>
>
> Carlos Matías
> @py_litox <https://twitter.com/py_litox>
>
> 2017-03-03 10:26 GMT-03:00 Juan Pablo Hernández Vogt <jphv.mail en gmail.com>
> :
>
>> Buenos días gente,
>>
>> Como todo nuevo en Python tengo un problema al usar eval() que no
>> entiendo. Parece que hay algo relacionado al evironment en el que es
>> ejecutado.
>>
>> Aquí un ejemplo mínimo que arroja el siguiente error:
>>
>> *NameError: name 'CalculationMode' is not defined*
>>
>>
>> Si muevo la definicion de la clase *CalculationMode *a *base.py*, eval()
>> funcionará correctamente:
>>
>> {'passes': [-1, 0, -1, 0], 'DUMMY': True, 'GENERIC_NAME': 'dummy',
>> 'AMBIENT_TEMPERATURE': 293, 'PRESSURE': 1013.25, 'MODE':
>> <CalculationMode.Pass_3D: 1>}
>>
>>
>> *File: base.py*
>> class BaseObject(object):
>>     def __init__(self, parameters=None):
>>         self.parameters = parameters
>>
>>     def load_parameter(self, key, value):
>>         if self.parameters is None:
>>             self.parameters = {}
>>
>>         self.parameters[key] = eval(value)
>>
>>
>> *File: derived.py*
>> from base import *
>>
>> # Using aenum from: https://pypi.python.org/pypi/aenum/1.4.5
>> from aenum import Enum
>>
>> class CalculationMode(Enum):
>>     Pass_2D = 0
>>     Pass_3D = 1
>>
>>
>> class Derived(BaseObject):
>>     def __init__(self, parameters=None):
>>         super(Derived, self).__init__(parameters)
>>
>>
>> if __name__ == "__main__":
>>
>>     obj = Derived()
>>
>>     obj.load_parameter('GENERIC_NAME', '"dummy"')
>>     obj.load_parameter('AMBIENT_TEMPERATURE', '293')
>>     obj.load_parameter('PRESSURE', '1013.25')
>>     obj.load_parameter('DUMMY', 'True')
>>     obj.load_parameter('passes', '[-1, 0, -1, 0]')
>>
>>     print(obj.parameters)
>>
>>     print("load enumeration")
>>     obj.load_parameter('MODE', 'CalculationMode.Pass_3D')
>>     print(obj.parameters)
>>
>>
>> Entonces, cómo hago para que el eval() definido en una clase base sepa
>> sobre tipos definidos en sus clases derivadas?
>>
>> Se puede hacer de forma simple o se debe pasar un "contexto" como
>> parámetro?
>>
>>
>> Gracias por su tiempo!
>>
>> _______________________________________________
>> pyar mailing list pyar en python.org.ar
>> http://listas.python.org.ar/listinfo/pyar
>>
>> PyAr - Python Argentina - Sitio web: http://www.python.org.ar/
>>
>> La lista de PyAr esta Hosteada en USLA - Usuarios de Software Libre de
>> Argentina - http://www.usla.org.ar
>>
>
>
> _______________________________________________
> pyar mailing list pyar en python.org.ar
> http://listas.python.org.ar/listinfo/pyar
>
> PyAr - Python Argentina - Sitio web: http://www.python.org.ar/
>
> La lista de PyAr esta Hosteada en USLA - Usuarios de Software Libre de
> Argentina - http://www.usla.org.ar
>
------------ próxima parte ------------
Se ha borrado un adjunto en formato HTML...
URL: <http://listas.python.org.ar/pipermail/pyar/attachments/20170303/4234d924/attachment-0001.html>


Más información sobre la lista de distribución pyar