-2

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!

Addison
  • 403
  • 8
  • 24
  • 3
    Because that's not a valid Python identifier – jonrsharpe Nov 06 '18 at 21:53
  • @jonrsharpe Okay that makes sense. Is there a way I can force it to work? Maybe make it a raw string or something? – Addison Nov 06 '18 at 21:57
  • 1
    Why are you trying to do it at all? Just access the values you want *from the dictionary*? "Variable variables" are generally not a good idea. – jonrsharpe Nov 06 '18 at 21:58
  • @jonrsharpe It is part of a larger program where the user inputs a query such as "age > 45 and Dept. != Sales" and it will output all of the records that are characterized by an age larger than 45 and a department not equal to Sales. In my actual program, there are dozens of records. – Addison Nov 06 '18 at 22:00
  • @jonrsharpe I simplified it down for this post – Addison Nov 06 '18 at 22:00
  • 1
    But that doesn't mean you need to evaluate the content of the record like that. Parse the input to something usable. – jonrsharpe Nov 06 '18 at 22:03

1 Answers1

1

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)
Kingsley
  • 14,398
  • 5
  • 31
  • 53
  • Also, it's worth reading this answer about the dangers of using `eval()` - https://stackoverflow.com/questions/15197673/using-pythons-eval-vs-ast-literal-eval – Kingsley Nov 06 '18 at 22:09