Issue #16339: Document and test exec(stmt, globals, locals) form in Python 2.7.
This commit is contained in:
parent
508d7d356e
commit
1658797a9d
|
@ -978,18 +978,18 @@ The :keyword:`exec` statement
|
|||
exec_stmt: "exec" `or_expr` ["in" `expression` ["," `expression`]]
|
||||
|
||||
This statement supports dynamic execution of Python code. The first expression
|
||||
should evaluate to either a string, an open file object, or a code object. If
|
||||
it is a string, the string is parsed as a suite of Python statements which is
|
||||
then executed (unless a syntax error occurs). [#]_ If it is an open file, the file
|
||||
is parsed until EOF and executed. If it is a code object, it is simply
|
||||
executed. In all cases, the code that's executed is expected to be valid as
|
||||
file input (see section :ref:`file-input`). Be aware that the
|
||||
:keyword:`return` and :keyword:`yield` statements may not be used outside of
|
||||
function definitions even within the context of code passed to the
|
||||
:keyword:`exec` statement.
|
||||
should evaluate to either a string, an open file object, a code object, or a
|
||||
tuple. If it is a string, the string is parsed as a suite of Python statements
|
||||
which is then executed (unless a syntax error occurs). [#]_ If it is an open
|
||||
file, the file is parsed until EOF and executed. If it is a code object, it is
|
||||
simply executed. For the interpretation of a tuple, see below. In all cases,
|
||||
the code that's executed is expected to be valid as file input (see section
|
||||
:ref:`file-input`). Be aware that the :keyword:`return` and :keyword:`yield`
|
||||
statements may not be used outside of function definitions even within the
|
||||
context of code passed to the :keyword:`exec` statement.
|
||||
|
||||
In all cases, if the optional parts are omitted, the code is executed in the
|
||||
current scope. If only the first expression after :keyword:`in` is specified,
|
||||
current scope. If only the first expression after ``in`` is specified,
|
||||
it should be a dictionary, which will be used for both the global and the local
|
||||
variables. If two expressions are given, they are used for the global and local
|
||||
variables, respectively. If provided, *locals* can be any mapping object.
|
||||
|
@ -997,6 +997,13 @@ Remember that at module level, globals and locals are the same dictionary. If
|
|||
two separate objects are given as *globals* and *locals*, the code will be
|
||||
executed as if it were embedded in a class definition.
|
||||
|
||||
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.
|
||||
|
||||
.. versionchanged:: 2.4
|
||||
Formerly, *locals* was required to be a dictionary.
|
||||
|
||||
|
|
|
@ -61,6 +61,34 @@ class TestSpecifics(unittest.TestCase):
|
|||
except SyntaxError:
|
||||
pass
|
||||
|
||||
def test_exec_functional_style(self):
|
||||
# Exec'ing a tuple of length 2 works.
|
||||
g = {'b': 2}
|
||||
exec("a = b + 1", g)
|
||||
self.assertEqual(g['a'], 3)
|
||||
|
||||
# As does exec'ing a tuple of length 3.
|
||||
l = {'b': 3}
|
||||
g = {'b': 5, 'c': 7}
|
||||
exec("a = b + c", g, l)
|
||||
self.assertNotIn('a', g)
|
||||
self.assertEqual(l['a'], 10)
|
||||
|
||||
# Tuples not of length 2 or 3 are invalid.
|
||||
with self.assertRaises(TypeError):
|
||||
exec("a = b + 1",)
|
||||
|
||||
with self.assertRaises(TypeError):
|
||||
exec("a = b + 1", {}, {}, {})
|
||||
|
||||
# Can't mix and match the two calling forms.
|
||||
g = {'a': 3, 'b': 4}
|
||||
l = {}
|
||||
with self.assertRaises(TypeError):
|
||||
exec("a = b + 1", g) in g
|
||||
with self.assertRaises(TypeError):
|
||||
exec("a = b + 1", g, l) in g, l
|
||||
|
||||
def test_exec_with_general_mapping_for_locals(self):
|
||||
|
||||
class M:
|
||||
|
|
Loading…
Reference in New Issue