On Wed, Nov 2, 2011 at 9:54 PM, Jacob Holm <jh@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@gmail.com | Brisbane, Australia