8000 bpo-43605: Improve the documentation to exec() and eval() by congma · Pull Request #25039 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

bpo-43605: Improve the documentation to exec() and eval() #25039

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Further revise eval/exec documentations for consistency and accuracy.
The documentations for eval/exec are further modified for consistency
and accuracy.

- For both functions, the documentation mostly follows the following
  structure: description of arguments, default values for optional
  arguments, special treatment of the "__builtins__" key, and notices
  about limitations or other noteworthy material. Previously, the
  description about the special "__builtins__" key is intermingled with
  the description about default values for missing arguments. Now, these
  are in separate paragraphs. Also, it is stressed that the special key
  is inserted in-place.
- In the notice about limitations to dynamic eval/exec w.r.t. scopes,
  also mention the assignment expression succinctly.
- Remove the description that exec() with both globals and locals behave
  "as if" the source string is embedded in a class block. Again, a class
  block inside a function can access the non-locals, but this is not
  available to exec().
- Instead of mentioning passing the return values of globals() and
  locals() around, we now say that the programmer can construct their
  own namespaces based on their return values. The reason is that
  currently the semantics of locals() is not very well defined, and in
  the light of PEP 558 it may change in the future.  Explicitly
  constructing new namespaces is more predictable than using the "raw"
  return value of locals(). In the future, this part of the docs can be
  further updated to keep up with the new definition of locals().
- Omit the footnote to exec() about the parser only accepting Unix-style
  LF newlines. This piece of information is outdated.
- Other small fixes for grammar.
  • Loading branch information
congma committed Mar 29, 2021
commit 4ffc9cdc0ea9cfe0220f8dd1b556244a730511b9
127 changes: 63 additions & 64 deletions Doc/library/functions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -496,26 +496,29 @@ are always available. They are listed here in alphabetical order.

.. function:: eval(expression[, globals[, locals]])

This function supports the dynamic evaluation of Python expression. The
This function supports the dynamic evaluation of Python expressions. The
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
This function supports the dynamic evaluation of Python expressions. The
This function dynamically evaluates Python expressions. The

first argument can be a string or a code object. The optional arguments
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe link this to the documentation for code objects.

specify the globals and locals respectively. If provided, *globals* must be
a dictionary. If provided, *locals* can be any mapping object.
specify the global and local namespaces respectively. If provided,
*globals* must be a dictionary. If provided, *locals* can be any
:term:`mapping` object.

In the most common case, the *expression* argument is a string, and it is
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
In the most common case, the *expression* argument is a string, and it is
When the *expression* argument is a string, it is

Tighten the wording

parsed and evaluated as a Python expression (see the section
":ref:`expression-input`" in the Language Reference). The leading and
trailing spaces, tabs, and newlines are stripped.

The evaluation is performed using the *globals* and *locals* dictionaries as
the global and local namespaces. If the *globals* dictionary is present and
does not contain a value for the key ``"__builtins__"``, a reference to the
dictionary of the built-in module :mod:`builtins` is inserted under that key
before *expression* is parsed. That way, you can control what builtins are
available to the executed code by inserting your own ``"__builtins__"``
dictionary into *globals* before passing it to :func:`eval`. If the
*locals* dictionary is omitted, it defaults to the *globals* dictionary. If
both dictionaries are omitted, the expression is executed with the globals
and locals in the environment where :func:`eval` is called.
The evaluation is performed in the environment specified by the arguments
*globals* and *locals*. If both are omitted, by default it uses the
environment where :func`eval` is called. If only the *globals* argument is
given, the local namespace defaults to *globals*.

Before evaluation, the special key ``"__builtins__"`` is searched for in the
global namespace that is explicitly or impcitly specified for :func:`eval`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
global namespace that is explicitly or impcitly specified for :func:`eval`.
global namespace that is explicitly or implicitly specified.

If this key is not present, by default a reference to the dictionary of the
built-in module :mod:`builtins` is inserted *in-place* under that key, so
that built-in identifiers resolve to their usual built-in implementations.
By overriding the value for the key ``"__builtins__"`` in *globals*, you
can control what builtins are available to the expression being evaluated.

The return value is the result of the evaluated expression. Syntax errors
are reported as exceptions. For example:
Expand All @@ -541,20 +544,24 @@ are always available. They are listed here in alphabetical order.
.. note::

Dynamic evaluation at run-time is not equivalent to embedding the
expression in a Python program and having it compiled as a part of the
whole program. In particular, :func:`eval` does not have access to the
:term:`nested scopes <nested scope>` (non-locals) in the enclosing
environment (see the section ":ref:`dynamic-features`" in the Language
Reference chapter on name binding). Of note are some expressions, such
as :term:`lambdas <lambda>`, :ref:`comprehensions <comprehensions>`, and
:term:`generator expressions <generator expression>`, which create an
inner scope of their own. The interaction between these expressions and
:func:`eval` can be explicitly controlled by the parameters *globals* and
*locals* in the aforementioned manner.
expression at the same place in a Python program and having it compiled
as a part of the whole program; this is explained in the section
":ref:`dynamic-features`" in the Language Reference.

In particular, :func:`eval` does not have access to the :term:`nested
scopes <nested scope>` (non-locals) in the enclosing environment. Of
note are expressions such as :term:`lambdas <lambda>`,
:ref:`comprehensions <comprehensions>`, and :term:`generator expressions
<generator expression>` which create an inner scope of their own. Since
Python 3.8, the action of an assignment expression (see :pep:`572`) also
depends on scope information determined at compile-time. Interaction
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
depends on scope information determined at compile-time. Interaction
depends on scope information determined at compile time. Interaction

between these expressions and :func:`eval` can be explicitly controlled
by the arguments *globals* and *locals* in the aforementioned manner.

The built-in functions :func:`globals` and :func:`locals` return the
current global and local dictionary, respectively, which may be useful to
pass around for use as the second and third argument to :func:`eval`.
current global and local dictionaries respectively, which may be useful
for constructing namespaces passed as the second and third arguments to
:func:`eval`.

Dynamic execution of *statements* is supported by the :func:`exec`
function (see below).
Expand All @@ -564,31 +571,29 @@ are always available. They are listed here in alphabetical order.

.. function:: exec(object[, globals[, locals]])

This function supports dynamic execution of Python code. *object* must be
either a string 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 a code object, it is simply executed. In all
cases, the code that's executed is expected to be valid as file input (see
the section ":ref:`file-input`" in the Language Reference). Be aware that
the :keyword:`nonlocal`, :keyword:`yield`, and :keyword:`return` statements
may not be used outside of function definitions even within the context of
code passed to the :func:`exec` function. The return value is ``None``.

In all cases, if the optional arguments are omitted, the code is executed in
the current scope. If only *globals* is provided, it must be a dictionary,
which will be used for both the global and the local variables. If
*globals* and *locals* are given, they are used for the global and local
variables, respectively. If provided, *locals* can be any mapping object.
Remember that at module level, globals and locals are the same dictionary.
If exec gets two separate objects as *globals* and *locals*, the code will
be executed as if it were embedded in a class definition.

If the *globals* dictionary does not contain a value for the key
``"__builtins__"``, a reference to the dictionary of the built-in module
:mod:`builtins` is inserted under that key. That way you can control what
builtins are available to the executed code by inserting your own
``"__builtins__"`` dictionary into *globals* before passing it to
:func:`exec`.
This function supports the dynamic execution of Python code. *object* must
be either a string 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 a code object, it is simply executed. In
all cases, the code being executed is expected to be valid as file input
(see the section ":ref:`file-input`" in the Language Reference). The return
value of :func:`exec` is ``None``.

If provided, *globals* must be a dictionary. If provided, *locals* can be
any mapping object.

The execution is performed in the environment specified by the arguments
*globals* and *locals*. If both are omitted, by default it uses the
environment where :func`exec` is called. If only the *globals* argument is
given, the local namespace defaults to *globals*.

Before execution, the special key ``"__builtins__"`` is searched for in the
global namespace that is explicitly or impcitly specified for :func:`exec`.
If this key is not present, by default a reference to the dictionary of the
built-in module :mod:`builtins` is inserted *in-place* under that key, so
that built-in identifiers resolve to their usual built-in implementations.
By overriding the value for the key ``"__builtins__"`` in *globals*, you
can control what builtins are available to the code being executed.

.. audit-event:: exec code_object exec

Expand All @@ -597,19 +602,19 @@ are always available. They are listed here in alphabetical order.

.. note::

Like :func:`eval`, :func:`exec` is :ref:`limited by constraints
particular to dynamic code execution and namespaces
<eval_limitation_dynamic>`. The built-in functions :func:`globals` and
:func:`locals` return the current global and local dictionary,
respectively, which may be useful to pass around for use as the second
and third argument to :func:`exec`.
Like :func:`eval`, :func:`exec` is limited by constraints particular to
:ref:`dynamic code execution and namespaces <eval_limitation_dynamic>`.
The built-in functions :func:`globals` and :func:`locals` return the
current global and local dictionaries respectively, which may be useful
for constructing namespaces passed as the second and third arguments to
:func:`exec`.

.. note::

The default *locals* act as described for function :func:`locals` below:
modifications to the default *locals* dictionary should not be attempted.
Pass an explicit *locals* dictionary if you need to see effects of the
code on *locals* after function :func:`exec` returns.
You can explicitly pass a distinct *locals* dictionary to :func:`exec` to
observe the effects of executing the code on the local namespace.


.. function:: filter(function, iterable)
Expand Down Expand Up @@ -1974,9 +1979,3 @@ are always available. They are listed here in alphabetical order.
.. versionchanged:: 3.9
When the command line options :option:`-E` or :option:`-I` are being used,
the environment variable :envvar:`PYTHONCASEOK` is now ignored.

.. rubric:: Footnotes

.. [#] Note that the parser only accepts the Unix-style end of line convention.
If you are reading the code from a file, make sure to use newline conversion
mode to convert Windows or Mac-style newlines.
0