diff --git a/pep-0338.txt b/pep-0338.txt index a2a21c85c..d611f74b5 100644 --- a/pep-0338.txt +++ b/pep-0338.txt @@ -8,7 +8,7 @@ Type: Standards Track Content-Type: text/x-rst Created: 16-Oct-2004 Python-Version: 2.5 -Post-History: 8-Nov-2004, 11-Feb-2006 +Post-History: 8-Nov-2004, 11-Feb-2006, 12-Feb-2006 Abstract @@ -142,36 +142,25 @@ The delegation has the form:: ``run_module`` is only one of a number of functions ``runpy`` exposes to make it easier to run Python code dynamically. The proposed functions are listed below (the descriptions are taken from the proposed -documenation). +documentation). -``run_code(code[, globals])`` +``run_code(code[, globals][, locals])`` Execute the supplied Python code object or string of source code and - return the resulting module globals dictionary. If supplied, the - optional globals dictionary is used as the module globals. - Otherwise, a new dictionary is used. + return the resulting locals dictionary. + + The optional ``globals`` argument may be used to specify the + dictionary to use as the ``globals()`` dictionary when running the + code. If the argument is omitted, a new dictionary is used. + + The ``locals`` argument may be used to specify the + dictionary to use as the ``locals()`` dictionary when running the + code. If it is omitted, the same dictionary is used as is used for + ``globals()``. + The special variable ``__builtins__`` in the globals dictionary is automatically initialised with a reference to the top level - namespace of the ``__builtin__`` module. - -``run_function_code(code[, globals][, locals])`` - - Execute the supplied function code object and return a tuple - containing the resulting globals and locals dictionaries. If - supplied, the optional globals dictionary is used as the module - globals. Otherwise, a new dictionary is used. Similarly, if - supplied, the optional locals dictionary is used as the function - locals. Otherwise, a new dictionary is used. - - As for ``run_code()`` the special variable ``__builtins__`` in the - globals dictionary is automatically initialised with a reference to - the top level namespace of the ``__builtin__`` module. - - A function code object is required, as module level Python code - cannot resolve names correctly when the locals and globals - dictionaries are not the same (specifically, new names are bound in - the locals dictionary, but this dictionary is not used when looking - up references to names at module level from inside a function). + namespace of the ``__builtin__`` module. ``run_module_code(code[, init_globals][, mod_name][, mod_file]\ @@ -186,12 +175,12 @@ documenation). variables below are defined in the supplied dictionary, those definitions are overridden. - The special global variables ``__name__``, ``__file__``, - ``__loader__`` and ``__builtins__`` are set in the globals - dictionary before the module code is executed. ``__name__``, - ``__file__``, ``__loader__`` are set based on the optional arguments - ``mod_name``, ``mod_file`` and ``mod_loader``. If the arguments are - omitted, the corresponding special variable is set to ``None``. + The special global variables ``__name__``, ``__file__``, and + ``__loader__`` are set in the globals dictionary before the module + code is executed. ``__name__``, ``__file__``, ``__loader__`` are + set based on the optional arguments ``mod_name``, ``mod_file`` and + ``mod_loader``. If the arguments are omitted, the corresponding + special variable is set to ``None``. If the argument ``as_script`` is supplied and evaluates to ``True``, then ``sys.argv[0]`` is updated with the value of ``mod_file`` @@ -229,6 +218,9 @@ documenation). level function is ``run_name`` if this optional argument is supplied and ``None`` otherwise. + The ``mod_loader`` argument to the lower level function is set to + ``None`` and the ``mod_file`` argument is set to ``filename``. + ``run_compiled_file(filename[, init_globals][, run_name]\ [, as_script])`` @@ -241,6 +233,9 @@ documenation). level function is ``run_name`` if this optional argument is supplied and ``None`` otherwise. + The ``mod_loader`` argument to the lower level function is set to + ``None`` and the ``mod_file`` argument is set to ``filename``. + ``run_file(filename[, init_globals][, run_name][, as_script])`` Execute the specified Python file and return the resulting module @@ -257,6 +252,9 @@ documenation). level function is ``run_name`` if this optional argument is supplied and ``None`` otherwise. + The ``mod_loader`` argument to the lower level function is set to + ``None`` and the ``mod_file`` argument is set to ``filename``. + When invoked as a script, the ``runpy`` module finds and executes the module supplied as the first argument. It adjusts ``sys.argv`` by @@ -272,46 +270,14 @@ There were some key design decisions that influenced the development of the ``runpy`` module. These are listed below. - the ``-m`` switch really only needs the ``run_module`` function. The - other six functions are included to give the module API coverage + other five functions are included to give the module API coverage of the other sources of executable Python code (strings, code objects source files, compiled files). -- when using ``exec`` with a separate locals dictionary, name resolution - only works right if the code being executed was compiled expecting - that the locals dictionary and the globals dictionary were different. - Module level code, and anything compiled using ``compile()`` (such as - a source string passed to ``exec``) assumes that the two dictionaries - are the same. If they're different, references to globals from inside - functions aren't resolved using the locals dictionary:: - - >>> code = """ - ... x = 1 - ... print x - ... def f(): - ... print "Try to resolve x from inside a function" - ... print x - ... f() - ... """ - >>> exec code - 1 - Try to resolve x from inside a function - 1 - >>> exec code in {} - 1 - Try to resolve x from inside a function - 1 - >>> exec code in {}, {} - 1 - Try to resolve x from inside a function - Traceback (most recent call last): - File "", line 1, in - File "", line 7, in - File "", line 6, in f - NameError: global name 'x' is not defined - - Accordingly, the basic ``run_code`` function doesn't accept a locals - dictionary, and the ``run_function_code`` function checks that the - supplied code object expects locals and globals to be different. +- no attempt is made to conceal the quirks of the exec statement when it + comes to executing function code objects, or attempting to reference + module level names from inside functions when a separate locals + dictionary is supplied. - The special variables ``__name__``, ``__file__`` and ``__loader__`` are set in a module's global namespace before the module is executed. @@ -325,9 +291,9 @@ the ``runpy`` module. These are listed below. these variables are simply set to ``None`` when the relevant information cannot be determined. -- Lastly, there is no special protection on the as_script argument when - file information is not available. This may result in ``sys.srgv[0]`` - being set to ``None`` if file name information is not available. +- Lastly, there is no special protection on the as_script argument. + This may result in ``sys.argv[0]`` being set to ``None`` if file + name information is not available. Alternatives @@ -345,6 +311,12 @@ Both approaches were rejected as they do not meet the main goal of the ``-m`` switch -- to allow the full Python namespace to be used to locate modules for execution from the command line. +An earlier version of this PEP included some mistaken assumption +about the way ``exec`` handled locals dictionaries and code from +function objects. These mistaken assumptions led to some unneeded +design complexity which has now been removed - ``run_code`` shares all +of the quirks of ``exec``. + References ==========