I'm trying to do something like this for a project:
def printhi():
print("Hi")
myinput = input() # for example printhi()
exec(myinput)
Now I get an error, because exec() just starts a new session and ignores my functions and variables. How can I change that?
The exec builtin takes two additional arguments that can be used to pass in the local and global scope:
x = 10
exec("print(x)", globals(), locals()) # Prints "10"
Update: Given your example, I think a "better" solution (or at least something more realistic) is to not use exec. To call a function given by the user, try something like:
mypinput = input()
choices = {'printhi': printhi}
if myinput in choices:
function = choices[myinput]
function()
else:
print("Unknown function", myinput)
Related
I'm trying to dynamically generate a function from user input. The user gives a function as a string input, gives the differents parameters, and I want to write a function that will change this string into a usable function. My idea so far was to use the exec function to create a lambda function constructed with a string like so : exec("f = lambda {}:{}".format(', '.join(['x'] + parameter_list), function_string)). This would give, for example, a string like "f = lambda x, a:x+a" to the exec function.
This technique works fine if I define the scope of exec to globals(), but I'd like my function to be local so that I can do something like this:
def define_function(function_string, parameter_list):
exec("f = lambda {}:{}".format(', '.join(['x'] + parameter_list), function_string))
return f
or like this :
def define_function(function_string, parameter_list):
exec("return lambda {}:{}".format(', '.join(['x'] + parameter_list), function_string))
However, in the first case, it gives an error along the lines of "f is not defined". In the second case, meanwhile, it says that "return can only be used in a function". I understand why the second error occurs, but I wonder why my first try didn't work. Using globals() makes it work, but I'd rather not use it.
If you have any suggestions for other methods for achieving the same result, I'm interested in those as well.
EDIT
Using eval also raises an error :
line 9, in define_function
eval("f = lambda {}:{}".format(', '.join(['x'] + parameter_list), function_string))
File "<string>", line 1
f = lambda x, a:x+a
^
SyntaxError: invalid syntax
Solution 1: use eval():
def get_func(param_list, result_str):
return eval("lambda {}: {}".format(', '.join(['x'] + param_list), result_str))
Solution 2: if you really want to use exec(), do something like this:
def get_func(param_list, result_str):
exec("f = lambda {}: {}".format(', '.join(['x'] + param_list), result_str))
return locals()['f']
Some good info on the differences between exec and eval here: What's the difference between eval, exec, and compile?
I can see what you're trying to do in your question, by the way, and it's worth noting that the documentation pages for exec() and locals() both explicitly warn that this won't work. Ditto, if you type help(locals) into the interactive interpreter, you get this message:
Help on built-in function locals in module builtins:
locals()
Return a dictionary containing the current scope's local variables.
NOTE: Whether or not updates to this dictionary will affect name lookups in
the local scope and vice-versa is *implementation dependent* and not
covered by any backwards compatibility guarantees.
While writing a program in python i noticed that if one puts a function like print("hello world") inside a variable it will not be stored like expected, instead it will run. Also when i go and call the variable later in the program it will do nothing. can anyone tell me why this is and how to fix it?
If mean something like:
variable = print("hello world")`
then calling the function is the expected result. This syntax means to call the print function and assign the returned value to the variable. It's analogous to:
variable = input("Enter a name")
You're surely not surprised that this calls the input() function and assigns the string that the user entered to the variable.
If you want to store a function, you can use a lambda:
variable = lambda: print("hello world")
Then you can later do:
variable()
and it will print the message
All, I have this request but first I will explain what I'm trying to achieve. I coded a python script with many global variables but also many methods defined inside different modules (.py files).
The script sometimes moves to a method and inside this method I call another method defined in another module. The script is quite complex.
Most of my code is inside Try/Except so that every time an exception is triggered my code runs a method called "check_issue()" in which I print to console the traceback and then I ask myself if there's any variable's value I want to double check. Now, I read many stackoverflow useful pages in which users show how to use/select globals(), locals() and eval() to see current global variables and local variables.
What I would specifically need though is the ability to input inside method "check_issue()" the name of a variable that may be defined not as global and not inside the method check_issue() either.
Using classes is not a solution since I would need to change hundreds of lines of code.
These are the links I already read:
Viewing all defined variables
Calling variable defined inside one function from another function
How to get value of variable entered from user input?
This is a sample code that doesn't work:
a = 4
b = "apple"
def func_a():
c = "orange"
...
check_issue()
def check_issue():
print("Something went wrong")
var_to_review = input("Input name of var you want to review")
# I need to be able to enter "c" and print the its value "orange"
print(func_a.locals()[var_to_review ]) # this doesn't work
Could somebody suggest how to fix it?
Many thanks
When you call locals() inside check_issue(), you can only access to the locals of this function, which would be : ['var_to_review'].
You can add a parameter to the check_issue function and pass locals whenever you call it.
a = 4
b = "apple"
def func_a():
c = "orange"
check_issue(locals())
def check_issue(local_vars):
print("Something went wrong")
var_to_review = input("Input name of var you want to review")
print(local_vars[var_to_review])
I am trying to make a script in Python, that when executed, asks the user for a function name and prints the function .__doc__
For example:
>>> print abs.__doc__
abs(number) -> number
Return the absolute value of the argument.
The problem is, it doesn't work with raw_input. The following is my code and what happens when it gets executed.
Code:
f = raw_input("Your function: ")
print f.__doc__
Execution:
Your function: abs
str(object='') -> string
Return a nice string representation of the object.
If the argument is a string, the return value is the same object.
What am I doing wrong?
Well you ask to print the __doc__ of f and f is in this case something like 'abs'. So you call 'abs'.__doc__ which is the __doc__ of a string.
Now you can however query for a builtin function with:
func = getattr(__builtins__,f)
print func.__doc__
this will however only work for builtin functions. You can also look for globals() or locals() which are dictionaries storing the global and local variables respectively.
As others have said, your problem is trying to use the string reply from raw_input() as a function object. You could get the function object by calling getattr(), but you need to known which module it is in. OK, so you could go through the global namespace looking for it, but there is a much simpler solution, just use pydoc:
f = raw_input("Your function: ")
help(f)
In this case, abs is a method that you're querying the __doc__ on. The raw_input is converting the input value to a string, so what you're really executing the __doc__ on is a string.
You get the same results if you do this:
z = ''
print z.__doc__
def function1(arguments):
print("Function 1",arguments)
def function2(arguments):
print("Function 2",arguments)
userInput = input()
Is it possible for the user to enter a function and arguments and for said function to run. eg the user enters function2("Hello World")
Though you can always use eval to make this work but for reasons eval is evil, it is better to use a dictionary call back mechanism, notably
You can create a dictionary to bind the function with the names and call them with appropriate parameters
call_backs = {'function1': function1, 'function2': function2}
assuming you provide an input as follows function2, "Hello World",
You first need to split the data userInput = userInput .split(',') and pass it onto the callback function via the dictionary
call_backs[userInput[0]](userInput[1])