I'm trying to evaluate a string in a Flask project, but I keep getting this error.
File "<string>", line 0
^
SyntaxError: unexpected EOF while parsing
This is the code I am using
def f(x):
input = "math.log((math.sin(x)**2) + 1) - (1 / 2)"
string = input.replace("x",str(x))
result = eval(string)
return result
Because replace is a method of the string class, it must be called from the string itself.
def f(x):
input = "math.log((math.sin(x)**2) + 1) - (1 / 2)"
string = input.replace("x",str(x))
result = eval(string)
return result
But, you should avoid calling eval unless you absolutely have to; eval is evil. Eval (and its cousin exec) can open up your program to arbitrary code injections.
Can you explain your usecase a little more and I can see if I can suggest a better alternative?
Why wouldn’t this work:
def f(x):
return math.log((math.sin(x)**2) + 1) - (1 / 2)
Try to change
result = eval(string)
return result
to
return eval(string)
Related
In python3, if a function with recursive invoking is injected into exec() in a function, I got an error.
For example, below code
def B(pys):
exec(pys)
pys="""
def fibonacci(n):
if n == 1 or n == 2:
r = 1
else:
r = fibonacci(n - 1) + fibonacci(n - 2)
return r
print(fibonacci(3))
"""
B(pys)
will raise NameError.
$ py -3.8 testrecursivefun.py
Traceback (most recent call last):
File "testrecursivefun.py", line 14, in <module>
B(pys)
File "testrecursivefun.py", line 2, in B
exec(pys)
File "<string>", line 9, in <module>
File "<string>", line 6, in fibonacci
NameError: name 'fibonacci' is not defined
If I run exec(pys) directly under the module, the exception disappeared.
The reason has been described in another question How does exec work with locals?. But I still don't know how I can figure out the recursive invoking in exec(). Because the function name is dynamic for me. I cannot add it to locals() to exec(). Who can help me figure it out.
For the sake of an answer, you can wrap your code in a function so the recursive function is in its local scope:
import textwrap
def B(pys):
exec(pys, globals(), {})
pys="""
def fibonacci(n):
if n == 1 or n == 2:
r = 1
else:
r = fibonacci(n - 1) + fibonacci(n - 2)
return r
print(fibonacci(11))
"""
def wrap(s):
return "def foo():\n" \
"{}\n" \
"foo()".format(textwrap.indent(s, ' ' * 4))
B(wrap(pys))
Generally, reconsider using exec.
I actually got interested in your question, so I started researching on this topic. Seems like the simple solution to your problem is to:
First compile the string to code using compile function in python
Then execute the compiled code using exec function
Here is the sample solution:
psy="""
def fibonacci(n):
if n == 1 or n == 2:
r = 1
else:
r = fibonacci(n - 1) + fibonacci(n - 2)
return r
print(fibonacci(3))
"""
def B(psy):
code = compile(psy, '<string>', 'exec')
exec(code, globals())
B(psy)
Here compile takes three parameters:
First is the code in string format, Second is the filename hint which we used as we take string as code itself, and third can be one of 'exec', 'eval' and 'single'.
This link contains detail explanation of how you should use exec and eval in python. Do check them out for detail explanation.
I have a problem that requires to return a string of numbers with the round function. Here is my code:
def get_percentage(num, round_digits):
if round_digits is None:
return str(num * 100) + "%"
else:
return str(round(num * 100, round_digits)) + "%"
The problem occurs when I try to call get_percentage with just 1 argument. Is there any way to fix this?
Please help. Thank You.
You can define the function with a default argument
def get_percentage(num, round_digits=None):
then you can call it with just the first argument.
Do you mean you want to call the function without supplying the round_digits argument?
Try this:
def get_percentage(num, round_digits=None):
if round_digits is None:
return str(num * 100) + "%"
else:
return str(round(num * 100, round_digits)) + "%"
By adding =None after the argument round_digits you're identifying a default value. And therefore, not required.
I'd like to know how I would go about doing something like this (in python 2):
def myFunction(fn, params):
return ("You called " + fn.__name__ + "(" + str(params) ")" +
" and got " + str(fn(params)))
Say I have a couple functions:
def doSomething(s):
# manipulation
return s
def doAnotherThing(someInt, someOtherInt, someString):
# do something with them
return someValue
I'd like to be able to call myFunction(doSomething, "hello"), and get You called doSomething("hello") and got "something". This approach seems to work for functions that take a single input, but I can't get it to work for functions that take multiple inputs, e.g. calling myFunction(doAnotherThing, (myInt, myOtherInt, myString)). I think I need to do something involving * and ** so that I can take the keywords arbitrarily instead of as a tuple, but I'm not quite sure how to go about doing that.
You're close, all you need to do is add a * in front of the tuple (or ** in front of a dict for keyword arguments) when calling the interior function. This is called argument unpacking.
def wrapper(fn, params, keyword_params):
return fn(*params, **keyword_params)
def myfunc(a, b, c=0):
return (a + b)/c
wrapper(myfunc, (2, 5), {'c': 3})
You can also use arbitrary argument lists to potentially simplify the wrapper function. This will allow you to automatically package additional arguments to feed to interior functions without having to pre-package them in tuples and dictionaries.
def wrapper(fn, *params, **keyword_params): # Note the asterisks
return fn(*params, **keyword_params)
def myfunc(a, b, c=1):
return (a + b)/c
wrapper(myfunc, 2, 5, c=3) # Nicer function call
Note that just using the first method will actually break single-argument implementations, as the * operator expects an iterator to unpack. So you have to either always pre-package the arguments or add some type-checking in the wrapper function.
def wrapper(fn, params):
return fn(*params)
def myfunc(a):
return 2*a
wrapper(myfunc, 2)
# TypeError: myfunc() argument after * must be a sequence, not int
wrapper(myfunc, (2,)) # Package the argument in a single-element tuple
# 4
The second method doesn't have this problem.
Here is one way:
def myFunction(fn, *params):
return ("You called " + fn.__name__ + str(params) +
" and got " + str(fn(*params)))
import math
print myFunction(math.sqrt, 4)
print myFunction(open, '/etc/passwd', 'r')
print myFunction(lambda x: x+1, 41)
Result:
You called sqrt(4,) and got 2.0
You called open('/etc/passwd', 'r') and got <open file '/etc/passwd', mode 'r' at 0x7f20e9cb65d0>
You called <lambda>(41,) and got 42
I have a file with a lot of lines like this
f(a, b)
f(abc, def)
f(a, f(u, i))
...
and I was asked to write a program in Python that would translate the strings into the following format:
a+b
abc+def
a+(u+i)
...
Rule: f(a, b) -> a+b
The approach I am following right now uses eval functions:
def f(a, b):
return "({0} + {1})".format(a,b)
eval("f(f('b','a'),'c')")
which returns
'((b + a) + c)'
However, as you can see, I need to put the letters as strings so that the eval function does not throw me a NameError when I run it.
Is there any way that will allow me to get the same behavior out of the eval function but without declaring the letters as strings?
eval is overkill here. this is just a simple string processing exercise:
replace the first 'f(' and the last ')' with ''
replace all remaining 'f(' with '('
replace all ', ' with '+'
and you're done.
this assumes that the only time the characters 'f(' appear next to each other is when it's supposed to represent a call to function f.
Yes, you can. The key is to use a mapping which returns the string as a key when it is missing.
>>> class Mdict(dict):
... def __missing__(self, k):
... return k
...
>>> eval('foo + bar', Mdict())
'foobar'
Of course, the general caveats about eval apply -- Please don't use it unless you trust the input completely.
You could use the shlex module to give yourself a nice token stack and then parse it as a sort of push down automaton.
>>> import shlex
>>> def parsef(tokens):
ftok = tokens.get_token() # there's no point to naming these tokens
oparentok = tokens.get_token() # unless you want to assert correct syntax
lefttok = tokens.get_token()
if 'f' == lefttok:
tokens.push_token(lefttok)
lefttok = "("+parsef(tokens)+")"
commatok = tokens.get_token()
righttok = tokens.get_token()
if 'f' == righttok:
tokens.push_token(righttok)
righttok = "("+parsef(tokens)+")"
cparentok = tokens.get_token()
return lefttok+"+"+righttok
>>> def parseline(line):
return parsef(shlex.shlex(line.strip()))
>>> parseline('f(a, b)')
'a+b'
>>> parseline('f(abc, def)')
'abc+def'
>>> parseline('f(a, f(u, i))')
'a+(u+i)'
Note that this assumes you are getting correct syntax.
I've got a function:
def user_login(m):
m = "user_login function called"
return m
Calling it with:
user_login(message)
It should change a string, m, and return the result. I know that the function gets called because it throws up an error [user_login() takes exactly 1 argument (0 given)] if I don't put an argument in it. But it doesn't return a string. How can I find out what's wrong?
You can't "change the string" - instead, what you should be doing, is assigning the result of the function to your string in the calling scope:
m = user_login('some message')
print m