eval() method - error inside function usage

General discussions and questions abound development of code with MicroPython that is not hardware specific.
Target audience: MicroPython Users.
Post Reply
User avatar
Zoland
Posts: 20
Joined: Wed Jan 23, 2019 2:12 pm
Location: Russia, Altai

eval() method - error inside function usage

Post by Zoland » Thu Mar 07, 2019 2:50 pm

I try to use eval() method in my practice, but in simple case code work,

Code: Select all

 1	def foo(**kwargs):
 2	    print('From foo: ',kwargs)
 3	    return True
 4
 5	dev_no = [{'name':'dev1','exec':'foo'},
 6		  {'name':'dev2','exec':'foo'}]
 7	print('-----------------------')
 8	print(eval(dev_no[0]['exec']+'(**dev_no[0])'))
 9
10	print('-----------------------')
11	def proc( devs ):
12	    print(eval(devs['exec']+'(**devs)'))
13	proc(dev_no[0])
but when I try to do the same in the function proc(dev_no[0]) - followed NameError

Code: Select all

	MPY: soft reboot
	-----------------------
	From foo: {'name': 'dev1', 'exec': 'foo'}
	True
	-----------------------
	Traceback (most recent call last):
	  File "main.py", line 13, in <module>
	  File "main.py", line 12, in proc
	  File "<string>", line 1, in <module>
	NameError: name 'devs' isn't defined
	MicroPython v1.10-98-g4daee3170 on 2019-02-14; ESP32 module with ESP32
What's wrong?

fstengel
Posts: 55
Joined: Tue Apr 17, 2018 4:37 pm

Re: eval() method - error inside function usage

Post by fstengel » Thu Mar 07, 2019 6:02 pm

What seems to be happening is that eval seems to be working in the global scope. The following works:

Code: Select all

def foo(**kwargs):
    print('From foo: ',kwargs)
    return True

dev_no = [{'name':'dev1','exec':'foo'},
        {'name':'dev2','exec':'foo'}]

dd = dev_no[0]

def proc( devs ):
    global dd
    dd=devs
    print(eval(dd['exec']+'(**dd)'))
proc(dev_no[0])

User avatar
Zoland
Posts: 20
Joined: Wed Jan 23, 2019 2:12 pm
Location: Russia, Altai

Re: eval() method - error inside function usage

Post by Zoland » Fri Mar 08, 2019 4:27 am

Yes, I know this solution, that why I lost several days testing my code.

I want to separate modules and not to use Global data in my project Smart Manor .

One of solution I done, using code like CASE operator in C++

Code: Select all

def case( dev, **kwargs ):
return {
	‘RELAY’   : dev_Relay,
	‘DS18X20’ : dev_temps,
	‘DHT11’   : dev_temp_vs_hum,
	‘DHT22’   : dev_temp_vs_hum,
	‘BME280’  : dev_temp_vs_hum_vs_pres,
	‘MQ2’     : dev_smoke,
	‘BELL’    : dev_beep,
}.get( dev,         dev_No )( **kwargs)
but it's look like heavy decision for me, I want to set most parameters in CONFIG file for each MCU as:

Code: Select all

id2 = {
    'name': 'Boil',
    'hard': uname().machine,
    'soft': 'Micropython:'+uname().version,
    'state': 0,                    # NEW,UPD,DEL,OK - barrier flag

    'devs': [

      { 'name':'temps',
        'type':'DS18X20',
        'bus' :{'type':'1wire','DATA':13},
        'set' :{'T1':(0,4,'r2'),'T2':(-2,7,'r1')},
        'get' :{'T1':12.34,'T2':567.891,'T3':2.3},
        'exec':'dev_temps'
        },

      { 'name':'r1',
        'type':'RELAY',
        'bus' :{'type':'1wire','DATA':14},
        'set' :{'On':True},
        'get' :{'On':True},
        'exec':'dev_relay'
        },

      { 'name':'r2',
        'type':'RELAY',
        'bus' :{'type':'1wire','DATA':15},
        'set' :{'On':True},
        'get' :{'On':True},
        'exec':'dev_relay'
        }
    ]
}
where 'exec' define module (handler) for each Sensor or Relay

User avatar
Zoland
Posts: 20
Joined: Wed Jan 23, 2019 2:12 pm
Location: Russia, Altai

Re: eval() method - error inside function usage

Post by Zoland » Sat Mar 09, 2019 5:39 am

In MicriPython differences from CPython I found:

Code running in eval() function doesn’t have access to local variables
Cause: MicroPython doesn’t maintain symbolic local environment, it is optimized to an array of slots. Thus, local variables can’t be accessed by a name. Effectively, eval(expr) in MicroPython is equivalent to eval(expr, globals(), globals()).

Code: Select all

val = 1

def test():
    val = 2
    print(val)
    eval("print(val)")

test()

Code: Select all

 CPy    UPy out
 -------------------
   2    2
   2    1

Post Reply