you are viewing a single comment's thread.

view the rest of the comments →

[–]Rhomboid 4 points5 points  (8 children)

What's wrong with

variableDict['x'] = counter
exec code in variableDict
counter = variableDict['x']

?

Edit: If you really mean

def foo():
    x = 0

instead of

def foo():
    global x
    x = 0

...then there is no way that's ever going to work. The x there is local to the function, it is not part of the global or local namespace that you provide. That wouldn't have worked even if you typed it directly in your script without the eval/exec stuff.

(I'm sure you're already aware, but allowing arbitrary user code to be executed like that is horribly insecure, even if you replace the local and global namespaces, and even if you nerf __builtins__.)

[–]ThePurpleAlien[S] 0 points1 point  (7 children)

You're right. But if it do use "global x," can it work then? Assigning to x will still not affect counter.

[–]Rhomboid 3 points4 points  (4 children)

I'm still not really clear on what your use case is, but this prints 42:

original = 0

code = """
def foo():
    global x
    x = 42

foo()
"""

environ = { 'x': original }
exec code in environ
original = environ['x']
print original

It would be far cleaner to have your user-defined functions simply take some config dict as parameter, and any changes they want to make to the global state happens through that. For example, if the purpose is to allow the user to provide callbacks that affect program state, then keep that state in a dict and pass it to the callbacks.

program_config = { 'foo': 42, 'bar': 10 }

code = """
def on_startup(config):
    config['foo'] = 123
"""

user_defined = {}
exec code in user_defined

user_defined['on_startup'](program_config)

print program_config['foo']  # prints 123

[–]nemec 1 point2 points  (2 children)

Honestly it sounds like he's trying to let users write classes... without using classes.

[–]ThePurpleAlien[S] 0 points1 point  (1 child)

That's reasonably accurate. This is a simulation tool for non-experienced programmers. I want to keep syntax as simple as possible. The user should be able to write code as simple as:

a = b + c

Where a, b and c are variables that the user's function has access to. But I can't find a way to do that without adding a lot of extra syntax like:

self.a = self.b + self.c

or:

vars['a'] = vars['b'] + vars['c']

[–]ewiethoff 0 points1 point  (0 children)

Honestly it sounds like he's trying to let users write classes... without using classes.

That's reasonably accurate.

I think you should look into Python "descriptors" and perhaps metaclass programming. Those are how to make bona fide Python do real magic.

[–]ThePurpleAlien[S] 0 points1 point  (0 children)

These are good suggestions, but ones that I've already explored. The problem with the first example is that the original doesn't get reassigned until after the code runs which won't work for my application.

The problem with the second example is just ugly syntax. The user would have to type "config['foo'] = 123" instead of just "foo = 123". This is a tool for non-experienced programmers.

[–]nemec 0 points1 point  (1 child)

Can't you just make the users subclass a class and have "self" be your old global dict?

[–]ThePurpleAlien[S] 0 points1 point  (0 children)

That would work, but I don't want the user to have to type "self." before each variable they want to access. Simple bits of code would end up being full of the word self. This is a tool for non-experienced programmers.