NYCeyes
NYCeyes

Reputation: 5659

Assistance with Python's ast.literal_eval('a_string')

I've been trying to get Python3s ast.literal_eval() function to work (in an interactive Python session) but -- and I read it's doc description -- I cannot.

My goal is to replace this:

>>> import logging
>>> eval('logging.DEBUG')
10

with the safer alternative, this:

>>> import logging, ast
>>> ast.literal_eval('logging.DEBUG')
Traceback (most recent call last):
...
ValueError: malformed node or string: <_ast.Attribute object at 0x7f1ccc55eeb8>

but the latter doesn't work (at least not how I am using it). Note that I also tried triple-quoted and raw-string variations, too.

I believe I'm simply missing a nuance here (e.g. it's possible that it may not like evaluating constants in a module). From the Python-3 documentation on ast.literal_eval():

Safely evaluate an expression node or a string containing a Python literal or container display. The string or node provided may only consist of the following Python literal structures: strings, bytes, numbers, tuples, lists, dicts, sets, booleans, and None.

This can be used for safely evaluating strings containing Python values from untrusted sources without the need to parse the values oneself. It is not capable of evaluating arbitrarily complex expressions, for example involving operators or indexing.

Any help appreciated. =:) Thank you in advance!

Upvotes: 5

Views: 3492

Answers (1)

Serge Ballesta
Serge Ballesta

Reputation: 148880

With the context you give in comment, I advice you not to do that:

  • you cannot use ast.literal_eval because logging.Debug is not a litteral: you ask a value from a module, and that could have arbitrary side effects
  • you should not use eval for a value that is read from an external file.

My advice would be to use a map:

log_levels = { 'DEBUG': logging.DEBUG, ... }

When you later read log_level (say DEBUG) from your config file, you just do:

real_level = log_levels[log_level]

That way you can easily accept case errors with real_level = log_levels[log_level.upper()], and if there is an unexpected value in the config file, you just get a KeyError exception, with no risk of unwanted evaluation.

Upvotes: 4

Related Questions