Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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!

like image 970
NYCeyes Avatar asked Mar 31 '16 15:03

NYCeyes


1 Answers

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.

like image 151
Serge Ballesta Avatar answered Nov 12 '22 02:11

Serge Ballesta