1

I am using triple quoted string, have if-else conditions inside the string, and defining the value of variable as per the conditions, and I am not able to use the variable outside the the string.

I tried writing whole class inside of triple quoted string, and it works, I am able to use the variable outside the triple quoted string.

It Works when whole class is inside the triple quote, it prints the variable 'a':

import pystache

codeBlock = '''
class GetData():
    def foo(): 
        a = 0
        if({{c}} ==  5):
            a = {{d}} * 5;
        elif({{c}} >= 5 and {{c}} < 10):
            a = {{d}} * 4;
        elif({{c}}<5):
            a = {{d}} * 10;

        return a

'''

codeBlock1 = pystache.render(codeBlock, {'c': 3,'d':10})
compiledCodeBlock = compile(codeBlock1, '<string>', 'exec')
eval(compiledCodeBlock)
print(GetData.foo())

output: 
>python a.py runserver
>100

And what I want is, the variable 'a' to be printed when the code block does not contain the whole class itself in the following case: (I am not sure if that's possible or not)

import pystache
class GetData():
    def foo(): 
        a = 0
        codeBlock = '''
if({{c}} ==  5): 
    print('one');
    a = {{d}} * 5;
elif({{c}} >= 5 and {{c}} < 10): 
    print('two');
    a = {{d}} * 4;
elif({{c}}<5):
    print('three');
    a = {{d}} * 10; 
        '''
        codeBlock1 = pystache.render(codeBlock,  {'c': 3,'d':10})
        compiledCodeBlock = compile(codeBlock1, '<string>', 'exec')
        eval(compiledCodeBlock)
        print(a)  # results -> 0

print(GetData.foo())  # results -> None

Output:
>python b.py runserver
>three
>0
>None

Expected Output:

value of a, i.e. 100

Parth
  • 13
  • 4

1 Answers1

0

Got it, you need to use globals parameter in either eval or exec. This allows you to pass a dictionary that will be used as initial value for named variables, and it will be updated acoordingly by evaluated code and returned.

class GetData():
    def foo(): 
        a = 0
        codeBlock = '''
if({c} ==  5): 
    print('one');
    a = {d} * 5;
elif({c} >= 5 and {c} < 10): 
    print('two');
    a = {d} * 4;
elif({c}<5):
    print('three');
    a = {d} * 10;
        '''
        codeBlock1 = codeBlock.format(c=3,d=10)
        compiledCodeBlock = compile(codeBlock1, '<string>', 'exec')
        loc = {'a':0}
        eval(compiledCodeBlock, loc)
        #print(loc['a'])  # results -> 100
        return loc['a']

print(GetData.foo())  # results -> 100

So you can see I'm creating a dictionary loc = {'a':0} which contains a a 'variable'. This is passed to eval and correlated with variables used in code. So if you do :

codeBlock = '''
print(a);
…
'''

the output is

0 --this is initial value in the dictionary

three

100

I hope it's clear enough.

Piotr Kamoda
  • 956
  • 1
  • 9
  • 24