How to evaluate python string boolean expression using eval()? - python

I get boolean expression like below :
string = '!True && !(True || False || True)'
I know eval('1+2') returns 3. But when I am executing eval(string) it is throwing me error as in invalid syntax.
Is there any other way I can execute the above expression?

None of !, && and || are valid Python operators; eval() can only handle valid Python expressions.
You'd have to replace those expressions with valid Python versions; presumably ! is not, && is and, and || is or, so you could just replace those with the Python versions:
eval(string.replace('&&', 'and').replace('||', 'or').replace('!', 'not '))
Note the space after not because Python requires this.
The better approach would be to not use the wrong spelling for those operators (they look like Java or JavaScript or C).

If you want to parse boolean logic (in contrast to control flow) take a look at this stackoverflow post. It mentions pyparsing
The pyparsing module is an alternative approach to creating and executing simple grammars
and sympy.
The logic module for SymPy allows to form and manipulate logic expressions using symbolic and boolean value.
There also seems to be a parser implemented with pyparsing.
Of course you could also write a parser yourself.

Related

How can I turn a string that contains numbers and operators into a result?

I want to convert this string into a result n for the output to be 11.
a = "1+5*6/3"
print (a)
The eval() built-in function can evaluate a Python expression including any arithmetic expression. But note the eval() function is a security concern because it can evaluate any arbitrary Python expression or statement so should be used only if the input to evaluate is controlled and trusted user input. There are examples to why eval() is dangerous in this question.
a = "1+5*6/3"
result = eval(a)
print(result)
Output:
11.0
Using ast module as an alternative to eval()
A safe alternative to eval() is using ast.literal_eval. Recent Python 3 versions disallows passing simple strings to ast.literal_eval() as an argument. Now must parse the string to buld an Abstract Syntax Tree (AST) then evaluate it against a grammar. This related answer provides an example to evaluate simple arithmetic expressions safely.
You can directly use the python eval function.
a = eval("1+5*6/3")
print(a)

Net Use in Python 3

anyone could help me with python trying to use NET use, I don't know the diferences between / in python and perl, because code in perl works
$runMap = "C:\\Windows\\System32\\net.exe use \\\\$ip\\D\$ /persistent:no /user:$user_name $passwd";
system($runMap);
But in Python 3 don't work
os.system("C:/Windows/System32/net.exe use Z: \\\\ip/D:/ /persistent:no /user:user pass")
Perl is using interpolation, that is, it is possible to embed variables inside a double quoted string, since Perl 5 interpolated variables start with a $ or a # marker. In your case you are embedding $user_name and $passwd.
Python variable names are not prefixed by a "magic character" (sigil), so you cannot embed them inside strings except by using formatting statements. There are a couple of regimes, here is one which is a similar idea to printf:
cmd = "C:/Windows/System32/net.exe use Z: \\\\ip/D:/ /persistent:no /user:%s %s" % (username, passwd)
os.system(cmd)
As an ex-Perlmonger I missed interpolation so much I wrote a Python module to support it. While I learnt a lot about Python doing it, it was otherwise a waste of time. Python programming is a different style, you don't need interpolation any more.
By the way, unlike Perl's system(), Python's os.system() will always spawn a shell (as does C's). Therefore it is generally considered to be deprecated. The subprocess.Popen() method gives much more control.
EDIT:
With the advent of Python 3.6 and Literal String Interpolation (specified in PEP 498) - more commonly known as f-strings - my original post needs another way to do it.
Single or double quotes may be used, even triple quotes. Basically we just put the Python expression, commonly a variable, inside braces (similar to Ruby).
So, for example:
os.system(f"C:/Windows/System32/net.exe use Z: \\\\ip/D:/ /persistent:no /user:{username} {passwd}")
The comment about subprocess.Popen() is also out of date, since Python 3.5 the preferred interface is now subprocess.run().

How to use not logical operation in python

inputing an logical expression as string and evaluating, i'm getting proper output
str1 = "(1|0)&(1|1&(0|1))"
print eval(str1)
o/p: 1
But the same way if i'm including not operator as ~, the output goes wrong.
str1 = "(~0|~1)&(~1|0)"
print eval(str1)
o/p: -2
Is there any other way of representing not operator here to get proper answer.
These are not logical expressions but bitwise expressions. That is the reason why ~0 == -1. Instead you can look for a parser that parses these expressions the way you want. A quick google search showed up this stackoverflow question.
Sympy seems to implement a similar thing: sympy logic
The logic module for SymPy allows to form and manipulate logic expressions using symbolic and boolean values
&, | and ~ are bitwise operators.
For logic operators use and, or and not.
If your intention is to do logical operations, prefer to use the appropriate boolean values:
True / False
str1 = "(not 0|not 1) and (not 1|0)"
print eval(str1)
In python NOT is not
Ref : https://docs.python.org/2/library/stdtypes.html

Parsing list to create python code

I have a list that I have successfully converted into a python statment
ex:
from operator import mul,add,sub,abs
l = ['add(4,mul(3,abs(-3)))']
I was wondering what would I use to RUN this string as actual python code? I should be expecting a output of 13. I want to input the 0th value of the list into a function that is able to run this value as actual python code.
You don't want to run this as Python code. You're trying to parse expressions in some language that isn't Python, even if it may be superficially similar. Even if it's a proper subset of Python, unless, say, __import__('os').system('rm -rf /') happens to be a valid string in the language that you want to handle by erasing the hard drive, using eval or exec is a bad idea.
If the grammar is a proper subset of Python, you can still use the ast module for parsing, and then write your own interpreter for the parsed nodes.
However, I think what you really want to do here is build a very simple parser for your very simple language. This is a great opportunity to learn how to use a parsing library like pyparsing or a parser-generator tool like pybison, or to build a simple recursive-descent parser from scratch. But for something this simple, even basic string operations (splitting on/finding parentheses) should be sufficient.
Here's an intentionally stupid example (which you definitely shouldn't turn in if you want a good grade) to show how easy it is:
import operator
OPERATORS = operator.__dict__
def evaluate_expression(expr):
try:
return int(expr)
except ValueError:
pass
op, _, args = expr.rpartition('(')
rest, _, thisop = op.rpartition(',')
args = args.rstrip(')').split(',')
argvalues = map(int, args)
thisvalue = OPERATORS[thisop](*argvalues)
if rest:
return evaluate_expression('{},{}'.format(rest, thisvalue))
return thisvalue
while True:
expr = input()
print(evaluate_expression(expr))
Normally, you want to find the outermost expression, then evaluate it recursively—that's a lot easier than finding the rightmost, substituting it into the string, and evaluating the result recursively. Again, I'm just showing how easy it is to do even if you don't do it the easy way.
use exec like this:
exec('add(4,mul(3,abs(-3)))')
That should work
more about exec
If you want to evaluate a Python expression, use eval. This returns the value of the evaluated expression. So, for example:
>>> eval(l[0])
13
>>> results = [eval(expr) for expr in l]
>>> results
[13]
However, any time you find yourself using eval (or exec or related functionality), you're almost always doing something wrong. This blog post explains some of the reasons why.
since you're evaluating an expression, eval would suit you better than exec. Example:
x = -3
y = eval('add(4,mul(3,abs(x)))')
print y
Note the security implication of exec and eval, since they can execute arbitrary code, including for example deleting all files you have access, installing Trojans to your doc files, etc.
Check out also ast.literal_eval for python 2.6+.

How can I convert a Perl regex with named groups to Python?

I am trying to convert the following Perl regex I found in the Video::Filename Perl module to a Python 2.5.4 regex to parse a filename
# Perl > v5.10
re => '^(?:(?<name>.*?)[\/\s._-]*)?(?<openb>\[)?(?<season>\d{1,2})[x\/](?<episode>\d{1,2})(?:-(?:\k<season>x)?(?<endep>\d{1,2}))?(?(<openb>)\])(?:[\s._-]*(?<epname>[^\/]+?))?$',
I would like to use named groups too, and I know in Python the regex extension for named groups is different, but I am not 100% sure on the syntax.
This is what I tried:
# Python (not working)
r = re.compile(r'^(?:(?P<name>.*?)[\/\s._-]*)?(?P<openb>\[)?(?P<season>\d{1,2})[x\/](?P<episode>\d{1,2})(?:-(?:\kP<season>x)?(?P<endep>\d{1,2}))?(?(P<openb>)\])(?:[\s._-]*(?P<epname>[^\/]+?))?$')
The error I get:
raise error, v # invalid expression
sre_constants.error: bad character in group name
For example, this one I managed to convert and it works. But the one above I can't seem to get right. I get a compilation error in Python.
# Perl:
re => '^(?:(?<name>.*?)[\/\s._-]+)?(?:s|se|season|series)[\s._-]?(?<season>\d{1,2})[x\/\s._-]*(?:e|ep|episode|[\/\s._-]+)[\s._-]?(?<episode>\d{1,2})(?:-?(?:(?:e|ep)[\s._]*)?(?<endep>\d{1,2}))?(?:[\s._]?(?:p|part)[\s._]?(?<part>\d+))?(?<subep>[a-z])?(?:[\/\s._-]*(?<epname>[^\/]+?))?$',
# Python (working):
r = re.compile(r'^(?:(?P<name>.*?)[\/\s._-]+)?(?:s|se|season|series)[\s._-]?(?P<season>\d{1,2})[x\/\s._-]*(?:e|ep|episode|[\/\s._-]+)[\s._-]?(?P<episode>\d{1,2})(?:-?(?:(?:e|ep)[\s._]*)?(?P<endep>\d{1,2}))?(?:[\s._]?(?:p|part)[\s._]?(?P<part>\d+))?(?P<subep>[a-z])?(?:[\/\s._-]*(?P<epname>[^\/]+?))?$')
I am not sure where to start looking.
There are 2 problems with your translation. First of all, the second mention of openb has extra parenthesis around it making it a conditional expression, not a named expression.
Next is that you didn't translate the \k<season> backreference, Python uses (P=season) to match the same. The following compiles for me:
r = re.compile(r'^(?:(?P<name>.*?)[\/\s._-]*)?(?P<openb>\[)?(?P<season>\d{1,2})[x\/](?P<episode>\d{1,2})(?:-(?:(?P=season)x)?(?P<endep>\d{1,2}))?(?(openb)\])(?:[\s._-]*(?P<epname>[^\/]+?))?$')
If I were you, I'd use re.VERBOSE to split this expression over multiple lines and add copious documentation so you can keep understanding the expression in the future if this is something that needs to remain maintainable though.
(edited after realising the second openb reference was a conditional expression, and to properly translate the backreference).
I found the offending part but can't figure out what exactly is wrong without wrapping my mind around the whole thing.
r = re.compile(r'^(?:(?P<name>.*?)[\/\s._-]*)?(?P<openb>\[)?(?P<season>\d{1,2})[x\/](?P<episode>\d{1,2})(?:-(?:\kP<season>x)?(?P<endep>\d{1,2}))?
(?(P<openb>)\]) // this part here causes the error message
(?:[\s._-]*(?P<epname>[^\/]+?))?$')
The problem seems to be with the fact that group names in python must be valid python identifiers (check documentation). The parentheses seem to be the problem. Removing them gives
(?(P<openb>)\]) //with parentheses
(?P<openb>\]) //without parentheses
redefinition of group name 'openb' as group 6; was group 2
Those regexps are the product of a sick an twisted mind... :-)
Anyway, (?()) are conditions in both Python and Perl, and the perl syntax above looks like it should be the same as the Python syntax, i.e., it evaluates as true of the group named exists.
Where to start looking? The documentation for the modules are here:
http://docs.python.org/library/re.html
http://www.perl.com/doc/manual/html/pod/perlre.html
I may be wrong but you tried to get the backreference using :
(?:\k<season>x)
Isn't the syntax \g<name> in Python ?

Categories