Search code examples
python-3.xeval

eval() syntax error when the expression ends with a period


I am working on a program which evaluates a query for a database. Below I define a single record, and show the issue I get when using eval()

record = {'name': 'John_Smith', 'gender': 'M', 'age':45,'Dept.': 'Sales'}

query = "Dept. == 'Sales'"
#query = "gender == 'M'"

if eval(query, {__builtins__: None}, record):
    print(record)

The error I get is

File "<string>", line 1 Dept. == 'Sales' ^ SyntaxError: invalid syntax

if query = "gender == 'M'" (as seen in the comment), eval() does work. However, when query is "Dept. == 'Sales'", I get the syntax error. It is clear that the period is causing this problem (I tried with other keys from the dictionary and had no issues). Is there a reason it won't accept the period? Is there a way I can have eval() recognize the period?

Looking forward to your answers!

Thanks!


Solution

  • Python does not allow a period . as part of a simple variable name.

    Dept. = 'x'   # NOT OK
    dept = 'x'    # ok
    

    Variables must begin with a letter or underscore, and then can have more letters, numbers or underscores. A Period is used to reference class members, but that's another answer.

    The "Dept" string is part of a dictionary, so it has no visibility to python by this name. It can be referenced as part of the dictionary:

    if record["Dept."] == 'blah':
        ...
    

    So your code could work like this:

    record = {'name': 'John_Smith', 'gender': 'M', 'age':45,'start_date':'2010/05/01','salary': 50000,'Dept.': 'Sales'}
    
    query = "record['Dept.'] == 'Sales'"
    
    if eval(query):
        print(record)
    

    Since you are passing record to eval() as the third parameter (object of local variables), simply removing the period is enough.

    record = {'name': 'John_Smith', 'gender': 'M', 'age':45,'start_date':'2010/05/01','salary': 50000,'Dept': 'Sales'}
    
    query = "Dept == 'Sales'"
    
    if eval(query, {__builtins__: None}, record):
        print(record)