Permalink
Cannot retrieve contributors at this time
155 lines (114 sloc)
4.92 KB
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
peps/pep-0288.txt
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| PEP: 288 | |
| Title: Generators Attributes and Exceptions | |
| Author: Raymond Hettinger <python@rcn.com> | |
| Status: Withdrawn | |
| Type: Standards Track | |
| Content-Type: text/x-rst | |
| Created: 21-Mar-2002 | |
| Python-Version: 2.5 | |
| Post-History: | |
| Abstract | |
| ======== | |
| This PEP proposes to enhance generators by providing mechanisms for | |
| raising exceptions and sharing data with running generators. | |
| Status | |
| ====== | |
| This PEP is withdrawn. The exception raising mechanism was extended | |
| and subsumed into :pep:`343`. The attribute passing capability | |
| never built a following, did not have a clear implementation, | |
| and did not have a clean way for the running generator to access | |
| its own namespace. | |
| Rationale | |
| ========= | |
| Currently, only class based iterators can provide attributes and | |
| exception handling. However, class based iterators are harder to | |
| write, less compact, less readable, and slower. A better solution | |
| is to enable these capabilities for generators. | |
| Enabling attribute assignments allows data to be passed to and from | |
| running generators. The approach of sharing data using attributes | |
| pervades Python. Other approaches exist but are somewhat hackish | |
| in comparison. | |
| Another evolutionary step is to add a generator method to allow | |
| exceptions to be passed to a generator. Currently, there is no | |
| clean method for triggering exceptions from outside the generator. | |
| Also, generator exception passing helps mitigate the try/finally | |
| prohibition for generators. The need is especially acute for | |
| generators needing to flush buffers or close resources upon termination. | |
| The two proposals are backwards compatible and require no new | |
| keywords. They are being recommended for Python version 2.5. | |
| Specification for Generator Attributes | |
| ====================================== | |
| Essentially, the proposal is to emulate attribute writing for classes. | |
| The only wrinkle is that generators lack a way to refer to instances of | |
| themselves. So, the proposal is to provide a function for discovering | |
| the reference. For example:: | |
| def mygen(filename): | |
| self = sys.get_generator() | |
| myfile = open(filename) | |
| for line in myfile: | |
| if len(line) < 10: | |
| continue | |
| self.pos = myfile.tell() | |
| yield line.upper() | |
| g = mygen('sample.txt') | |
| line1 = g.next() | |
| print 'Position', g.pos | |
| Uses for generator attributes include: | |
| 1. Providing generator clients with extra information (as shown | |
| above). | |
| 2. Externally setting control flags governing generator operation | |
| (possibly telling a generator when to step in or step over | |
| data groups). | |
| 3. Writing lazy consumers with complex execution states | |
| (an arithmetic encoder output stream for example). | |
| 4. Writing co-routines (as demonstrated in Dr. Mertz's articles [1]_). | |
| The control flow of 'yield' and 'next' is unchanged by this | |
| proposal. The only change is that data can passed to and from the | |
| generator. Most of the underlying machinery is already in place, | |
| only the access function needs to be added. | |
| Specification for Generator Exception Passing | |
| ============================================= | |
| Add a ``.throw(exception)`` method to the generator interface:: | |
| def logger(): | |
| start = time.time() | |
| log = [] | |
| try: | |
| while True: | |
| log.append(time.time() - start) | |
| yield log[-1] | |
| except WriteLog: | |
| writelog(log) | |
| g = logger() | |
| for i in [10,20,40,80,160]: | |
| testsuite(i) | |
| g.next() | |
| g.throw(WriteLog) | |
| There is no existing work-around for triggering an exception | |
| inside a generator. It is the only case in Python where active | |
| code cannot be excepted to or through. | |
| Generator exception passing also helps address an intrinsic | |
| limitation on generators, the prohibition against their using | |
| try/finally to trigger clean-up code (:pep:`255`). | |
| Note A: The name of the throw method was selected for several | |
| reasons. Raise is a keyword and so cannot be used as a method | |
| name. Unlike raise which immediately raises an exception from the | |
| current execution point, throw will first return to the generator | |
| and then raise the exception. The word throw is suggestive of | |
| putting the exception in another location. The word throw is | |
| already associated with exceptions in other languages. | |
| Alternative method names were considered: ``resolve()``, ``signal()``, | |
| ``genraise()``, ``raiseinto()``, and ``flush()``. None of these fit as well | |
| as ``throw()``. | |
| Note B: To keep the ``throw()`` syntax simple only the instance | |
| version of the raise syntax would be supported (no variants for | |
| "``raise string``" or "``raise class, instance``"). | |
| Calling ``g.throw(instance)`` would correspond to writing | |
| ``raise instance`` immediately after the most recent yield. | |
| References | |
| ========== | |
| .. [1] Dr. David Mertz's draft columns for Charming Python | |
| http://gnosis.cx/publish/programming/charming_python_b5.txt | |
| http://gnosis.cx/publish/programming/charming_python_b7.txt | |
| Copyright | |
| ========= | |
| This document has been placed in the public domain. |