Reputation: 215
I'm trying to make a game engine in Python as a "weekend project" but I have a problem.
I'm trying to make it that a user can declare a keybind by typing the key and the function into a text file what they want to run but when I run the code from that sheet with exec it runs the function and I have no idea on how to call the function through the variable. (Also I don't want it to run the function when it runs the code.)
Here is the code I use for executing the code from binds.zdata
for line in bind:
try:
exec line
except:
try:
error.write(localtime + " : " + "ERROR: Could not bind key from the bind file : " + line)
except:
pass
Here's the text in binds.zdata
_w = Functions.motion.move().forward()
_a = Functions.motion.move().left()
_s = Functions.motion.move().back()
_d = Functions.motion.move().right()
Upvotes: 6
Views: 372
Reputation: 702
Reading the config like that with exec is going to open you to all kinds of pain at runtime, as the user's config file is going to be executable code that you are just trusting. Malicious or unintentionally just bad commands will get execute. You could template it like this:
def read_config(config_file):
user_button_map = {}
with open(config_file, 'r') as fh:
for line in fh.readlines():
key,func_key = line.strip().split(',')
assert(key in BUTTON_MAP_FUNCTIONS),"no such action"
user_button_map[key] = BUTTON_MAP_FUNCTIONS[func_key]
return user_button_map
BUTTON_MAP_FUNCTIONS = {
"forward" : Functions.motion.move().forward,
"left" : Functions.motion.move().left,
# etc...
}
# sample config file
# w, forward
# a, left
# etc...
Upvotes: 2
Reputation: 123413
I'd first change the lines in the binds.zdata file like this so they assign a function to each of the variables:
_w = Functions.motion.move().forward
_a = Functions.motion.move().left
_s = Functions.motion.move().back
_d = Functions.motion.move().right
Then, assuming that Functions
is defined, I'd execute all the lines in the file at once with something like:
try:
execfile('binds.zdata')
except Exception as exc:
error.write(localtime + " : " + "ERROR: executing binds file")
Afterwards, the _w
, _a
, _s
, _d
variables will have the desired function assigned to them, which you can call as usual — i.e. _w()
, _a()
, etc.
Upvotes: 3
Reputation: 1929
I'm not sure I recommend "exec" since somebody could put any code in there.
But here is your problem.
_w = Functions.motion.move().forward()
Calls the function 'forward' and puts the results in _w.
_w = Functions.motion.move().forward
Assigns the function 'forward' to the variable '_w'.
Since you asked what I would do, I would create a set of tokens that represent the various functions and then let them do the mapping in side a config file (see: ConfigParser). Then parse the config file. It is a little more work, but a lot more secure.
Upvotes: 4
Reputation: 27567
You want to lose the ()
at the end of each line:
_w = Functions.motion.move().forward
_a = Functions.motion.move().left
_s = Functions.motion.move().back
_d = Functions.motion.move().right
now you can call the function through the variable by simply applying parenthesis, such as:
_w()
Upvotes: 6