What does Python's eval() do?

前端 未结 10 2083
后悔当初
后悔当初 2020-11-22 01:48

In the book that I am reading on Python, it keeps using the code eval(input(\'blah\'))

I read the documentation, and I understand it, but I still do no

10条回答
  •  灰色年华
    2020-11-22 02:28

    Lots of good answers here, but none describe the use of eval() in the context of its globals and locals kwargs, i.e. eval(expression, globals=None, locals=None) (see docs for eval here).

    These can be used to limit the functions that are available through the eval function. For example if you load up a fresh python interpreter the locals() and globals() will be the same and look something like this:

    >>>globals()
    {'__loader__': , '__doc__': None,
     '__spec__': None, '__builtins__': ,
     '__package__': None, '__name__': '__main__'}
    

    There are certainly functions within the builtins module that can do significant damage to a system. But it is possible to block anything and everything we don't want available. Let's take an example. Say we want to construct a list to represent a domain of the available cores on a system. For me I have 8 cores so I would want a list [1, 8].

    >>>from os import cpu_count
    >>>eval('[1, cpu_count()]')
    [1, 8]
    

    Likewise all of __builtins__ is available.

    >>>eval('abs(-1)')
    1
    

    Ok. So there we see one function we want exposed and an example of one (of many that can be much more complex) method that we do not want exposed. So let's block everything.

    >>>eval('[1, cpu_count()]', {'__builtins__':None}, {})
    TypeError: 'NoneType' object is not subscriptable
    

    We have effectively blocked all of the __builtins__ functions and as such brought a level of protection into our system. At this point we can start to add back in functions that we do want exposed.

    >>>from os import cpu_count
    >>>exposed_methods = {'cpu_count': cpu_count}
    >>>eval('cpu_count()', {'__builtins__':None}, exposed_methods)
    8
    >>>eval('abs(cpu_count())', {'__builtins__':None}, exposed_methods)
    TypeError: 'NoneType' object is not subscriptable
    

    Now we have the cpu_count function available while still blocking everything we do not want. In my opinion, this is super powerful and clearly from the scope of the other answers, not a common implementation. There are numerous uses for something like this and as long as it is handled correctly I personally feel eval can be safely used to great value.

    N.B.

    Something else that is cool about these kwargs is that you can start to use shorthand for your code. Let's say you use eval as part of a pipeline to execute some imported text. The text doesn't need to have exact code, it can follow some template file format, and still execute anything you'd like. For example:

    >>>from os import cpu_count
    >>>eval('[1,cores]', {'__builtins__': None}, {'cores': cpu_count()})
    [1, 8]
    

提交回复
热议问题