[Python-ideas] Cofunctions - A New Protocol

Nick Coghlan ncoghlan at gmail.com
Thu Nov 3 02:51:10 CET 2011


On Wed, Nov 2, 2011 at 9:54 PM, Jacob Holm <jh at improva.dk> wrote:
> If the switch Nick describes is available as a flag on the frame
> objects, it would be easy to extend the traceback to show *exactly*
> where you entered the no-coroutine zone that you are now failing to
> suspend.  I don't think the additional syntax is helpful, and it would
> be quite annoying to need to have two versions of every wrapper
> function/decorator to make it useable in both contexts.

Indeed, this is an error reporting problem, not something to be solved
by maintaining the bifurcation of the language into
"coroutine-friendly" and "normal". Again, I go back to the (lack of)
contrast between code being run in the main process thread and code
being run as part of a separate OS level thread. There, the "boundary"
between the two is covered in the way the exception is reported:

>>> f()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in f
Exception
>>> threading.Thread(target=f).start()
>>> Exception in thread Thread-1:
Traceback (most recent call last):
  File "/usr/lib64/python3.2/threading.py", line 736, in _bootstrap_inner
    self.run()
  File "/usr/lib64/python3.2/threading.py", line 689, in run
    self._target(*self._args, **self._kwargs)
  File "<stdin>", line 2, in f
Exception

Heck, Thread + input Queue + output Queue may be an easier to
understand conceptual model for coroutine programming than generators.
While the internals would be completely different (since the whole
point of coroutines is to avoid the OS level thread overhead), it may
help to give people the correct mental model of what is going on.

>>> def f():
...     print("Started")
...     data = cothread.suspend(1)
...     print("Resumed:", data)
...     return 42
...
>>> cf, data = cothread.cocall(f)
Started
>>> data
1
>>> cf.resume()
Resumed: None
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "cothread.py", line 80, in resume
    return self._wait_for_output()
  File "cothread.py", line 66, in _wait_for_output
    raise CoroutineReturn(data.args[0])
cothread.CoroutineReturn: 42

>>> cf, data = cothread.cocall(f)
Started
>>> cf.throw(Exception)
Traceback (most recent call last):
  File "cothread.py", line 34, in run
    result = self._target(*self._args, **self._kwargs)
  File "<stdin>", line 3, in f
  File "cothread.py", line 6, in suspend
    return current.suspend(*args, **kwds)
  File "cothread.py", line 98, in suspend
    raise exc
Exception

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "cothread.py", line 89, in throw
    return self._wait_for_output()
  File "cothread.py", line 70, in _wait_for_output
    raise type(exc)(*exc.args) from exc
Exception

-- 
Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia
-------------- next part --------------
A non-text attachment was scrubbed...
Name: cothread.py
Type: text/x-python
Size: 2982 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20111103/4c6179b8/attachment.py>


More information about the Python-ideas mailing list