Reputation: 699
In Lua, there's a built-in function called setfenv()
, which allows you to supply a table of variables as an environment for a function. Here's an example that uses it:
foo = 1
function f()
print(blech) --Note that no variable named blech has been defined.
end
variableTable = {blech = foo}
setfenv(f, variableTable)
f() -- This will work and print 1, because blech has been defined as foo's value in the variableTable
My motivation for doing this is that it allows me to set up a platform so that users can write easy-to-understand scripts in Lua (they can write nullary functions and can simply trust that variables will be there for them). It also provides an elegant method of excluding modules and functions that I don't want them to use for security reason (e.g. if you define a variable table that doesn't have the os module defined, there's no way a more knowledgeable user could use it maliciously).
I would like to be able to achieve the same thing in Python. Is there something similar that can be done in Python?
Upvotes: 1
Views: 3163
Reputation: 4222
Why would you ever want to do that? Did your code become too readable?
Just pass a dict or a struct with your 'env' to the function.
EDIT: read your motivation. First part i cannot understand (writing lua scripts in python? what does that mean?), the second is plain wrong. This is no way to restrict enviroment. For one, you can still import os
.
Restricted execution is kinda a complex topic. Some stuff i know of:
Upvotes: 2
Reputation: 48335
There's exec
:
def foo():
print bar
exec foo.func_code in {"bar": "baz"}
This isn't particularly good style (I would even say that it is particularly bad). It makes the implementation of foo
difficult to understand since it relies on knowing about the special way in which it will be called. Instead, pass arguments to functions.
This does not provide any measure of security. As a first approximation, Python does not include any restricted execution capabilities. Nothing stops a user from supplying this definition of foo instead:
def foo():
import os
os.system("rm -rf /")
Just because you didn't supply os
in the mapping doesn't mean they can't go get it themselves. If you really need restricted execution, then you might want to stick with Lua, or at least investigate PyPy sandboxed mode.
Upvotes: 5
Reputation: 46193
You can have your function take an extra value that is a blob of keyword arguments:
def printKeyValuePairs(preface, **kwargs):
print preface + "\n"
for k,v in kwargs.iteritems():
print k + ": " + v + "\n"
# usage
printKeyValuePairs("Here are my key-value pairs:", One=1, Two=2, Three=3)
# prints:
# Here are my key-value pairs:
# One: 1
# Two: 2
# Three: 3
# (note that the above lines could be ordered any which way... might want to
# sort first if it matters)
Upvotes: 0
Reputation: 37909
I'm not sure why you'd want to do this, but here is one hacky way:
def foo():
print bar
foo.func_globals['bar'] = 1
foo()
Caveat: This is not something I recommend doing.
Upvotes: 3
Reputation: 37441
I don't know of any sane way to do that. Just use function arguments.
def f(blech):
print(blech)
If you want it to have many variables, stick them in a dict
and pass that.
def f(vars):
print(vars['blech'])
print(vars['fizz'])
Upvotes: 0