Python | locals () function

locals | Python Methods and Functions

Symbol table: is a compiler-generated data structure used to store all the information needed to run a program. 
Local symbol table: This symbol table stores all the information required for the local scope of a program and is accessed using the Python built-in locals () function .

Syntax: locals ()

Parameters: This function does not take any input parameter.

Return Type: This returns the information stored in local symbol table.

Example # 1:

# Python program for understanding locals

# no local variable here

def demo1 () :

print (  "Here no local variable is present:" , locals ())

# local variables are present here

def demo2 ():

name = "Ankit"

print ( "Here local variables are present:" , locals ())

# driver code
demo1 ()
demo2 ()

Exit :

 Here no local variable is present: {} Here local variables are present: {'name':' Ankit'} 

Example # 2: Updating using locals () .

Unlike globals (), this function cannot modify local symbol table data. The program below explains it clearly.

# Python program for understanding locals

# no local variable here

def demo1 ():

print ( " Here no local variable is present: " , locals ())

# local variables are present here

def demo2 ():

name = "Ankit"

print ( "Here local variables are present:" , locals ())

print ( "Before updating name is :" , name)


# trying change name value

locals () [ 'name' ] = "Sri Ram"


print ( "after updating name is:" , name)

# driver code
demo1 ()
demo2 ()


 Here no local variable is present: {} Here local variables are present: {'name':' Ankit'} Before updating name is: Ankit after updating name is: Ankit 

Example # 3: locals () for the global environment .

The local symbol table is the same as the global symbol table for the global environment.

# Python program for understanding locals

# data using locals

print ( "This is using locals ():" , locals ())

# data using globals

print ( "This is using globals ():" , globals ())


This is using locals (): {'__file__': '/ home / ',' __doc__ ': None,' __name__ ':' __main__ ',' __cached__ ': None,' __spec__ ': None,' __builtins__ ': & lt-in module' )ins' (built , '__package__': None, '__loader__':% lt; _frozen_importlib_external.SourceFileLoader object at 0x7f88 5e463470 & gt;}
This is using globals (): {'__file__': '/home/', '__doc__': None, '__name__': '__main__', '__cached__': None ': None,' __builtins__ ': & lt; module' builtins' (built-in) & gt ;, '__package__': None, '__loader__': & lt; _frozen_importlib_external.SourceFileLoader object at 0x7f885e463470 & gtlock;}

Python | locals () function: StackOverflow Questions

What"s the difference between globals(), locals(), and vars()?

What is the difference between globals(), locals(), and vars()? What do they return? Are updates to the results useful?

Answer #1

Because [] and {} are literal syntax. Python can create bytecode just to create the list or dictionary objects:

>>> import dis
>>> dis.dis(compile("[]", "", "eval"))
  1           0 BUILD_LIST               0
              3 RETURN_VALUE        
>>> dis.dis(compile("{}", "", "eval"))
  1           0 BUILD_MAP                0
              3 RETURN_VALUE        

list() and dict() are separate objects. Their names need to be resolved, the stack has to be involved to push the arguments, the frame has to be stored to retrieve later, and a call has to be made. That all takes more time.

For the empty case, that means you have at the very least a LOAD_NAME (which has to search through the global namespace as well as the builtins module) followed by a CALL_FUNCTION, which has to preserve the current frame:

>>> dis.dis(compile("list()", "", "eval"))
  1           0 LOAD_NAME                0 (list)
              3 CALL_FUNCTION            0
              6 RETURN_VALUE        
>>> dis.dis(compile("dict()", "", "eval"))
  1           0 LOAD_NAME                0 (dict)
              3 CALL_FUNCTION            0
              6 RETURN_VALUE        

You can time the name lookup separately with timeit:

>>> import timeit
>>> timeit.timeit("list", number=10**7)
>>> timeit.timeit("dict", number=10**7)

The time discrepancy there is probably a dictionary hash collision. Subtract those times from the times for calling those objects, and compare the result against the times for using literals:

>>> timeit.timeit("[]", number=10**7)
>>> timeit.timeit("{}", number=10**7)
>>> timeit.timeit("list()", number=10**7)
>>> timeit.timeit("dict()", number=10**7)

So having to call the object takes an additional 1.00 - 0.31 - 0.30 == 0.39 seconds per 10 million calls.

You can avoid the global lookup cost by aliasing the global names as locals (using a timeit setup, everything you bind to a name is a local):

>>> timeit.timeit("_list", "_list = list", number=10**7)
>>> timeit.timeit("_dict", "_dict = dict", number=10**7)
>>> timeit.timeit("_list()", "_list = list", number=10**7)
>>> timeit.timeit("_dict()", "_dict = dict", number=10**7)

but you never can overcome that CALL_FUNCTION cost.

Answer #2

The short answer, or TL;DR

Basically, eval is used to evaluate a single dynamically generated Python expression, and exec is used to execute dynamically generated Python code only for its side effects.

eval and exec have these two differences:

  1. eval accepts only a single expression, exec can take a code block that has Python statements: loops, try: except:, class and function/method definitions and so on.

    An expression in Python is whatever you can have as the value in a variable assignment:

    a_variable = (anything you can put within these parentheses is an expression)
  2. eval returns the value of the given expression, whereas exec ignores the return value from its code, and always returns None (in Python 2 it is a statement and cannot be used as an expression, so it really does not return anything).

In versions 1.0 - 2.7, exec was a statement, because CPython needed to produce a different kind of code object for functions that used exec for its side effects inside the function.

In Python 3, exec is a function; its use has no effect on the compiled bytecode of the function where it is used.

Thus basically:

>>> a = 5
>>> eval("37 + a")   # it is an expression
>>> exec("37 + a")   # it is an expression statement; value is ignored (None is returned)
>>> exec("a = 47")   # modify a global variable as a side effect
>>> a
>>> eval("a = 47")  # you cannot evaluate a statement
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1
    a = 47
SyntaxError: invalid syntax

The compile in "exec" mode compiles any number of statements into a bytecode that implicitly always returns None, whereas in "eval" mode it compiles a single expression into bytecode that returns the value of that expression.

>>> eval(compile("42", "<string>", "exec"))  # code returns None
>>> eval(compile("42", "<string>", "eval"))  # code returns 42
>>> exec(compile("42", "<string>", "eval"))  # code returns 42,
>>>                                          # but ignored by exec

In the "eval" mode (and thus with the eval function if a string is passed in), the compile raises an exception if the source code contains statements or anything else beyond a single expression:

>>> compile("for i in range(3): print(i)", "<string>", "eval")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1
    for i in range(3): print(i)
SyntaxError: invalid syntax

Actually the statement "eval accepts only a single expression" applies only when a string (which contains Python source code) is passed to eval. Then it is internally compiled to bytecode using compile(source, "<string>", "eval") This is where the difference really comes from.

If a code object (which contains Python bytecode) is passed to exec or eval, they behave identically, excepting for the fact that exec ignores the return value, still returning None always. So it is possible use eval to execute something that has statements, if you just compiled it into bytecode before instead of passing it as a string:

>>> eval(compile("if 1: print("Hello")", "<string>", "exec"))

works without problems, even though the compiled code contains statements. It still returns None, because that is the return value of the code object returned from compile.

In the "eval" mode (and thus with the eval function if a string is passed in), the compile raises an exception if the source code contains statements or anything else beyond a single expression:

>>> compile("for i in range(3): print(i)", "<string>". "eval")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1
    for i in range(3): print(i)
SyntaxError: invalid syntax

The longer answer, a.k.a the gory details

exec and eval

The exec function (which was a statement in Python 2) is used for executing a dynamically created statement or program:

>>> program = """
for i in range(3):
    print("Python is cool")
>>> exec(program)
Python is cool
Python is cool
Python is cool

The eval function does the same for a single expression, and returns the value of the expression:

>>> a = 2
>>> my_calculation = "42 * a"
>>> result = eval(my_calculation)
>>> result

exec and eval both accept the program/expression to be run either as a str, unicode or bytes object containing source code, or as a code object which contains Python bytecode.

If a str/unicode/bytes containing source code was passed to exec, it behaves equivalently to:

exec(compile(source, "<string>", "exec"))

and eval similarly behaves equivalent to:

eval(compile(source, "<string>", "eval"))

Since all expressions can be used as statements in Python (these are called the Expr nodes in the Python abstract grammar; the opposite is not true), you can always use exec if you do not need the return value. That is to say, you can use either eval("my_func(42)") or exec("my_func(42)"), the difference being that eval returns the value returned by my_func, and exec discards it:

>>> def my_func(arg):
...     print("Called with %d" % arg)
...     return arg * 2
>>> exec("my_func(42)")
Called with 42
>>> eval("my_func(42)")
Called with 42

Of the 2, only exec accepts source code that contains statements, like def, for, while, import, or class, the assignment statement (a.k.a a = 42), or entire programs:

>>> exec("for i in range(3): print(i)")
>>> eval("for i in range(3): print(i)")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1
    for i in range(3): print(i)
SyntaxError: invalid syntax

Both exec and eval accept 2 additional positional arguments - globals and locals - which are the global and local variable scopes that the code sees. These default to the globals() and locals() within the scope that called exec or eval, but any dictionary can be used for globals and any mapping for locals (including dict of course). These can be used not only to restrict/modify the variables that the code sees, but are often also used for capturing the variables that the executed code creates:

>>> g = dict()
>>> l = dict()
>>> exec("global a; a, b = 123, 42", g, l)
>>> g["a"]
>>> l
{"b": 42}

(If you display the value of the entire g, it would be much longer, because exec and eval add the built-ins module as __builtins__ to the globals automatically if it is missing).

In Python 2, the official syntax for the exec statement is actually exec code in globals, locals, as in

>>> exec "global a; a, b = 123, 42" in g, l

However the alternate syntax exec(code, globals, locals) has always been accepted too (see below).


The compile(source, filename, mode, flags=0, dont_inherit=False, optimize=-1) built-in can be used to speed up repeated invocations of the same code with exec or eval by compiling the source into a code object beforehand. The mode parameter controls the kind of code fragment the compile function accepts and the kind of bytecode it produces. The choices are "eval", "exec" and "single":

  • "eval" mode expects a single expression, and will produce bytecode that when run will return the value of that expression:

    >>> dis.dis(compile("a + b", "<string>", "eval"))
      1           0 LOAD_NAME                0 (a)
                  3 LOAD_NAME                1 (b)
                  6 BINARY_ADD
                  7 RETURN_VALUE
  • "exec" accepts any kinds of python constructs from single expressions to whole modules of code, and executes them as if they were module top-level statements. The code object returns None:

    >>> dis.dis(compile("a + b", "<string>", "exec"))
      1           0 LOAD_NAME                0 (a)
                  3 LOAD_NAME                1 (b)
                  6 BINARY_ADD
                  7 POP_TOP                             <- discard result
                  8 LOAD_CONST               0 (None)   <- load None on stack
                 11 RETURN_VALUE                        <- return top of stack
  • "single" is a limited form of "exec" which accepts a source code containing a single statement (or multiple statements separated by ;) if the last statement is an expression statement, the resulting bytecode also prints the repr of the value of that expression to the standard output(!).

    An if-elif-else chain, a loop with else, and try with its except, else and finally blocks is considered a single statement.

    A source fragment containing 2 top-level statements is an error for the "single", except in Python 2 there is a bug that sometimes allows multiple toplevel statements in the code; only the first is compiled; the rest are ignored:

    In Python 2.7.8:

    >>> exec(compile("a = 5
    a = 6", "<string>", "single"))
    >>> a

    And in Python 3.4.2:

    >>> exec(compile("a = 5
    a = 6", "<string>", "single"))
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<string>", line 1
        a = 5
    SyntaxError: multiple statements found while compiling a single statement

    This is very useful for making interactive Python shells. However, the value of the expression is not returned, even if you eval the resulting code.

Thus greatest distinction of exec and eval actually comes from the compile function and its modes.

In addition to compiling source code to bytecode, compile supports compiling abstract syntax trees (parse trees of Python code) into code objects; and source code into abstract syntax trees (the ast.parse is written in Python and just calls compile(source, filename, mode, PyCF_ONLY_AST)); these are used for example for modifying source code on the fly, and also for dynamic code creation, as it is often easier to handle the code as a tree of nodes instead of lines of text in complex cases.

While eval only allows you to evaluate a string that contains a single expression, you can eval a whole statement, or even a whole module that has been compiled into bytecode; that is, with Python 2, print is a statement, and cannot be evalled directly:

>>> eval("for i in range(3): print("Python is cool")")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1
    for i in range(3): print("Python is cool")
SyntaxError: invalid syntax

compile it with "exec" mode into a code object and you can eval it; the eval function will return None.

>>> code = compile("for i in range(3): print("Python is cool")",
                   "", "exec")
>>> eval(code)
Python is cool
Python is cool
Python is cool

If one looks into eval and exec source code in CPython 3, this is very evident; they both call PyEval_EvalCode with same arguments, the only difference being that exec explicitly returns None.

Syntax differences of exec between Python 2 and Python 3

One of the major differences in Python 2 is that exec is a statement and eval is a built-in function (both are built-in functions in Python 3). It is a well-known fact that the official syntax of exec in Python 2 is exec code [in globals[, locals]].

Unlike majority of the Python 2-to-3 porting guides seem to suggest, the exec statement in CPython 2 can be also used with syntax that looks exactly like the exec function invocation in Python 3. The reason is that Python 0.9.9 had the exec(code, globals, locals) built-in function! And that built-in function was replaced with exec statement somewhere before Python 1.0 release.

Since it was desirable to not break backwards compatibility with Python 0.9.9, Guido van Rossum added a compatibility hack in 1993: if the code was a tuple of length 2 or 3, and globals and locals were not passed into the exec statement otherwise, the code would be interpreted as if the 2nd and 3rd element of the tuple were the globals and locals respectively. The compatibility hack was not mentioned even in Python 1.4 documentation (the earliest available version online); and thus was not known to many writers of the porting guides and tools, until it was documented again in November 2012:

The first expression may also be a tuple of length 2 or 3. In this case, the optional parts must be omitted. The form exec(expr, globals) is equivalent to exec expr in globals, while the form exec(expr, globals, locals) is equivalent to exec expr in globals, locals. The tuple form of exec provides compatibility with Python 3, where exec is a function rather than a statement.

Yes, in CPython 2.7 that it is handily referred to as being a forward-compatibility option (why confuse people over that there is a backward compatibility option at all), when it actually had been there for backward-compatibility for two decades.

Thus while exec is a statement in Python 1 and Python 2, and a built-in function in Python 3 and Python 0.9.9,

>>> exec("print(a)", globals(), {"a": 42})

has had identical behaviour in possibly every widely released Python version ever; and works in Jython 2.5.2, PyPy 2.3.1 (Python 2.7.6) and IronPython 2.6.1 too (kudos to them following the undocumented behaviour of CPython closely).

What you cannot do in Pythons 1.0 - 2.7 with its compatibility hack, is to store the return value of exec into a variable:

Python 2.7.11+ (default, Apr 17 2016, 14:00:29) 
[GCC 5.3.1 20160413] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> a = exec("print(42)")
  File "<stdin>", line 1
    a = exec("print(42)")
SyntaxError: invalid syntax

(which wouldn"t be useful in Python 3 either, as exec always returns None), or pass a reference to exec:

>>> call_later(exec, "print(42)", delay=1000)
  File "<stdin>", line 1
    call_later(exec, "print(42)", delay=1000)
SyntaxError: invalid syntax

Which a pattern that someone might actually have used, though unlikely;

Or use it in a list comprehension:

>>> [exec(i) for i in ["print(42)", "print(foo)"]
  File "<stdin>", line 1
    [exec(i) for i in ["print(42)", "print(foo)"]
SyntaxError: invalid syntax

which is abuse of list comprehensions (use a for loop instead!).

Answer #3

First, there"s actually a much less hacky way. All we want to do is change what print prints, right?

_print = print
def print(*args, **kw):
    args = (arg.replace("cat", "dog") if isinstance(arg, str) else arg
            for arg in args)
    _print(*args, **kw)

Or, similarly, you can monkeypatch sys.stdout instead of print.

Also, nothing wrong with the exec … getsource … idea. Well, of course there"s plenty wrong with it, but less than what follows here…

But if you do want to modify the function object"s code constants, we can do that.

If you really want to play around with code objects for real, you should use a library like bytecode (when it"s finished) or byteplay (until then, or for older Python versions) instead of doing it manually. Even for something this trivial, the CodeType initializer is a pain; if you actually need to do stuff like fixing up lnotab, only a lunatic would do that manually.

Also, it goes without saying that not all Python implementations use CPython-style code objects. This code will work in CPython 3.7, and probably all versions back to at least 2.2 with a few minor changes (and not the code-hacking stuff, but things like generator expressions), but it won"t work with any version of IronPython.

import types

def print_function():
    print ("This cat was scared.")

def main():
    # A function object is a wrapper around a code object, with
    # a bit of extra stuff like default values and closure cells.
    # See inspect module docs for more details.
    co = print_function.__code__
    # A code object is a wrapper around a string of bytecode, with a
    # whole bunch of extra stuff, including a list of constants used
    # by that bytecode. Again see inspect module docs. Anyway, inside
    # the bytecode for string (which you can read by typing
    # dis.dis(string) in your REPL), there"s going to be an
    # instruction like LOAD_CONST 1 to load the string literal onto
    # the stack to pass to the print function, and that works by just
    # reading co.co_consts[1]. So, that"s what we want to change.
    consts = tuple(c.replace("cat", "dog") if isinstance(c, str) else c
                   for c in co.co_consts)
    # Unfortunately, code objects are immutable, so we have to create
    # a new one, copying over everything except for co_consts, which
    # we"ll replace. And the initializer has a zillion parameters.
    # Try help(types.CodeType) at the REPL to see the whole list.
    co = types.CodeType(
        co.co_argcount, co.co_kwonlyargcount, co.co_nlocals,
        co.co_stacksize, co.co_flags, co.co_code,
        consts, co.co_names, co.co_varnames, co.co_filename,
        co.co_name, co.co_firstlineno, co.co_lnotab,
        co.co_freevars, co.co_cellvars)
    print_function.__code__ = co


What could go wrong with hacking up code objects? Mostly just segfaults, RuntimeErrors that eat up the whole stack, more normal RuntimeErrors that can be handled, or garbage values that will probably just raise a TypeError or AttributeError when you try to use them. For examples, try creating a code object with just a RETURN_VALUE with nothing on the stack (bytecode b"S" for 3.6+, b"S" before), or with an empty tuple for co_consts when there"s a LOAD_CONST 0 in the bytecode, or with varnames decremented by 1 so the highest LOAD_FAST actually loads a freevar/cellvar cell. For some real fun, if you get the lnotab wrong enough, your code will only segfault when run in the debugger.

Using bytecode or byteplay won"t protect you from all of those problems, but they do have some basic sanity checks, and nice helpers that let you do things like insert a chunk of code and let it worry about updating all offsets and labels so you can"t get it wrong, and so on. (Plus, they keep you from having to type in that ridiculous 6-line constructor, and having to debug the silly typos that come from doing so.)

Now on to #2.

I mentioned that code objects are immutable. And of course the consts are a tuple, so we can"t change that directly. And the thing in the const tuple is a string, which we also can"t change directly. That"s why I had to build a new string to build a new tuple to build a new code object.

But what if you could change a string directly?

Well, deep enough under the covers, everything is just a pointer to some C data, right? If you"re using CPython, there"s a C API to access the objects, and you can use ctypes to access that API from within Python itself, which is such a terrible idea that they put a pythonapi right there in the stdlib"s ctypes module. :) The most important trick you need to know is that id(x) is the actual pointer to x in memory (as an int).

Unfortunately, the C API for strings won"t let us safely get at the internal storage of an already-frozen string. So screw safely, let"s just read the header files and find that storage ourselves.

If you"re using CPython 3.4 - 3.7 (it"s different for older versions, and who knows for the future), a string literal from a module that"s made of pure ASCII is going to be stored using the compact ASCII format, which means the struct ends early and the buffer of ASCII bytes follows immediately in memory. This will break (as in probably segfault) if you put a non-ASCII character in the string, or certain kinds of non-literal strings, but you can read up on the other 4 ways to access the buffer for different kinds of strings.

To make things slightly easier, I"m using the superhackyinternals project off my GitHub. (It"s intentionally not pip-installable because you really shouldn"t be using this except to experiment with your local build of the interpreter and the like.)

import ctypes
import internals #

def print_function():
    print ("This cat was scared.")

def main():
    for c in print_function.__code__.co_consts:
        if isinstance(c, str):
            idx = c.find("cat")
            if idx != -1:
                # Too much to explain here; just guess and learn to
                # love the segfaults...
                p = internals.PyUnicodeObject.from_address(id(c))
                assert p.compact and p.ascii
                addr = id(c) + internals.PyUnicodeObject.utf8_length.offset
                buf = (ctypes.c_int8 * 3).from_address(addr + idx)
                buf[:3] = b"dog"



If you want to play with this stuff, int is a whole lot simpler under the covers than str. And it"s a lot easier to guess what you can break by changing the value of 2 to 1, right? Actually, forget imagining, let"s just do it (using the types from superhackyinternals again):

>>> n = 2
>>> pn = PyLongObject.from_address(id(n))
>>> pn.ob_digit[0]
>>> pn.ob_digit[0] = 1
>>> 2
>>> n * 3
>>> i = 10
>>> while i < 40:
...     i *= 2
...     print(i)

… pretend that code box has an infinite-length scrollbar.

I tried the same thing in IPython, and the first time I tried to evaluate 2 at the prompt, it went into some kind of uninterruptable infinite loop. Presumably it"s using the number 2 for something in its REPL loop, while the stock interpreter isn"t?

Answer #4

No, it doesn"t.

The compilation to CPython byte code is only passed through a small peephole optimizer that is designed to do only basic optimizations (See in the test suite for more on these optimizations).

To take a look at what"s actually going to happen, use dis* to see the instructions generated. For the first function, containing the assignment:

from dis import dis
  2           0 LOAD_CONST               1 (42)
              2 STORE_FAST               0 (a)

  3           4 LOAD_FAST                0 (a)
              6 RETURN_VALUE

While, for the second function:

  2           0 LOAD_CONST               1 (42)
              2 RETURN_VALUE

Two more (fast) instructions are used in the first: STORE_FAST and LOAD_FAST. These make a quick store and grab of the value in the fastlocals array of the current execution frame. Then, in both cases, a RETURN_VALUE is performed. So, the second is ever so slightly faster due to less commands needed to execute.

In general, be aware that the CPython compiler is conservative in the optimizations it performs. It isn"t and doesn"t try to be as smart as other compilers (which, in general, also have much more information to work with). The main design goal, apart from obviously being correct, is to a) keep it simple and b) be as swift as possible in compiling these so you don"t even notice that a compilation phase exists.

In the end, you shouldn"t trouble yourself with small issues like this one. The benefit in speed is tiny, constant and, dwarfed by the overhead introduced by the fact that Python is interpreted.

*dis is a little Python module that dis-assembles your code, you can use it to see the Python bytecode that the VM will execute.

Note: As also stated in a comment by @Jorn Vernee, this is specific to the CPython implementation of Python. Other implementations might do more aggressive optimizations if they so desire, CPython doesn"t.

Answer #5

While exec(open("filename").read()) is often given as an alternative to execfile("filename"), it misses important details that execfile supported.

The following function for Python3.x is as close as I could get to having the same behavior as executing a file directly. That matches running python /path/to/

def execfile(filepath, globals=None, locals=None):
    if globals is None:
        globals = {}
        "__file__": filepath,
        "__name__": "__main__",
    with open(filepath, "rb") as file:
        exec(compile(, filepath, "exec"), globals, locals)

# execute the file


  • Uses binary reading to avoid encoding issues
  • Guaranteed to close the file (Python3.x warns about this)
  • Defines __main__, some scripts depend on this to check if they are loading as a module or not for eg. if __name__ == "__main__"
  • Setting __file__ is nicer for exception messages and some scripts use __file__ to get the paths of other files relative to them.
  • Takes optional globals & locals arguments, modifying them in-place as execfile does - so you can access any variables defined by reading back the variables after running.

  • Unlike Python2"s execfile this does not modify the current namespace by default. For that you have to explicitly pass in globals() & locals().

Answer #6

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:

{"__loader__": <class "_frozen_importlib.BuiltinImporter">, "__doc__": None,
 "__spec__": None, "__builtins__": <module "builtins" (built-in)>,
 "__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.


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)
>>>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.


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]

Answer #7

eval: This is very powerful, but is also very dangerous if you accept strings to evaluate from untrusted input. Suppose the string being evaluated is "os.system("rm -rf /")" ? It will really start deleting all the files on your computer.

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, None, bytes and sets.


eval(expression, globals=None, locals=None)
import ast


# python 2.x - doesn"t accept operators in string format
import ast
ast.literal_eval("[1, 2, 3]")  # output: [1, 2, 3]
ast.literal_eval("1+1") # output: ValueError: malformed string

# python 3.0 -3.6
import ast
ast.literal_eval("1+1") # output : 2
ast.literal_eval("{"a": 2, "b": 3, 3:"xyz"}") # output : {"a": 2, "b": 3, 3:"xyz"}
# type dictionary
ast.literal_eval("",{}) # output : Syntax Error required only one parameter
ast.literal_eval("__import__("os").system("rm -rf /")") # output : error

eval("__import__("os").system("rm -rf /")") 
# output : start deleting all the files on your computer.
# restricting using global and local variables
eval("__import__("os").system("rm -rf /")",{"__builtins__":{}},{})
# output : Error due to blocked imports by passing  "__builtins__":{} in global

# But still eval is not safe. we can access and break the code as given below
s = """
(lambda fc=(
lambda n: [
    c for c in 
        if c.__name__ == n
eval(s, {"__builtins__":{}})

In the above code ().__class__.__bases__[0] nothing but object itself. Now we instantiated all the subclasses, here our main enter code hereobjective is to find one class named n from it.

We need to code object and function object from instantiated subclasses. This is an alternative way from CPython to access subclasses of object and attach the system.

From python 3.7 ast.literal_eval() is now stricter. Addition and subtraction of arbitrary numbers are no longer allowed. link

Answer #8

To check the existence of a local variable:

if "myVar" in locals():
  # myVar exists.

To check the existence of a global variable:

if "myVar" in globals():
  # myVar exists.

To check if an object has an attribute:

if hasattr(obj, "attr_name"):
  # obj.attr_name exists.

Answer #9




locals returns a dictionary with a current local symbol table. globals returns a dictionary with global symbol table.

Answer #10

Oh, the many, many ways...

String concatenation:

plot.savefig("hanning" + str(num) + ".pdf")

Conversion Specifier:

plot.savefig("hanning%s.pdf" % num)

Using local variable names:

plot.savefig("hanning%(num)s.pdf" % locals()) # Neat trick

Using str.format():

plot.savefig("hanning{0}.pdf".format(num)) # Note: This is the new preferred way

Using f-strings:

plot.savefig(f"hanning{num}.pdf") # added in Python 3.6

Using string.Template:


Get Solution for free from DataCamp guru