So, the little test program below does print a traceback with this code in place. ...
12 years, 6 months ago
(2013-05-03 16:45:57 UTC)
#1
So, the little test program below does print a traceback with this code in
place. But running the tests I also get a bunch of messages logged. Thoughts?
from tulip import *
@task
def go():
print('hiss')
yield from sleep(1)
print('boom')
1/0
def main():
l = get_event_loop()
go()
l.run_until_complete(sleep(2))
main()
On 2013/05/03 16:45:57, GvR wrote: > So, the little test program below does print a ...
12 years, 6 months ago
(2013-05-03 18:11:20 UTC)
#2
On 2013/05/03 16:45:57, GvR wrote:
> So, the little test program below does print a traceback with this code in
> place. But running the tests I also get a bunch of messages logged.
Thoughts?
>
> from tulip import *
>
> @task
> def go():
> print('hiss')
> yield from sleep(1)
> print('boom')
> 1/0
>
>
> def main():
> l = get_event_loop()
> go()
> l.run_until_complete(sleep(2))
>
> main()
in most tests we check exception, but this code prints exception imminently.
here is example:
def test__sock_sendall_exception(self):
f = futures.Future()
sock = unittest.mock.Mock()
sock.fileno.return_value = 10
err = sock.send.side_effect = OSError()
self.event_loop._sock_sendall(f, False, sock, b'data')
self.assertIs(f.exception(), err)
i think __del__ works fine for Future. We can create base class without __del__
and inherit Task from it.
On Fri, May 3, 2013 at 11:11 AM, <fafhrd91@gmail.com> wrote: > On 2013/05/03 16:45:57, GvR ...
12 years, 6 months ago
(2013-05-03 19:00:54 UTC)
#3
On Fri, May 3, 2013 at 11:11 AM, <fafhrd91@gmail.com> wrote:
> On 2013/05/03 16:45:57, GvR wrote:
>>
>> So, the little test program below does print a traceback with this
>
> code in
>>
>> place. But running the tests I also get a bunch of messages logged.
>
> Thoughts?
>
>> from tulip import *
>
>
>> @task
>> def go():
>> print('hiss')
>> yield from sleep(1)
>> print('boom')
>> 1/0
>
>
>
>> def main():
>> l = get_event_loop()
>> go()
>> l.run_until_complete(sleep(2))
>
>
>> main()
>
>
> in most tests we check exception, but this code prints exception
> imminently.
>
> here is example:
>
> def test__sock_sendall_exception(self):
> f = futures.Future()
> sock = unittest.mock.Mock()
> sock.fileno.return_value = 10
> err = sock.send.side_effect = OSError()
>
> self.event_loop._sock_sendall(f, False, sock, b'data')
> self.assertIs(f.exception(), err)
>
>
> i think __del__ works fine for Future. We can create base class without
> __del__ and inherit Task from it.
But then we can no longer document Task as a Future subclass, and to
check for "Task or Future" you have to use isinstance(x, BaseFuture)
which is pretty ugly.
Also it's easy to imagine a non-Task Future being part of a cycle,
which would cause nasty memory leaks if the cycle isn't broken. The
reality is that __del__ just isn't easy to use. :-(
The code you quote is test code, and it tests an internal API, so I'm
not too concerned if that's the only example.
Are there any cases in the actual Tulip code that creates a Future and
immediately sets its exception and then returns it in a context where
the exception is supposed to be inspected?
I have an idea for a design involving __del__ in a way that is
guaranteed not to have a cycle. I'll send you a CR soon.
--
--Guido van Rossum (python.org/~guido)
Patch Set 2 is my new idea. Get rid of the __del__ on the Future, ...
12 years, 6 months ago
(2013-05-03 19:26:54 UTC)
#4
Patch Set 2 is my new idea.
Get rid of the __del__ on the Future, but add a small object "dangling off the
side" that is guaranteed not to have any cycles (its only instance variable is a
list of strings). The __del__ on that side object will log those strings. When
the exception is requested through result() or exception() the side object is
reset and removed.
On 2013/05/03 19:26:54, GvR wrote: > Patch Set 2 is my new idea. > > ...
12 years, 6 months ago
(2013-05-03 19:35:48 UTC)
#5
On 2013/05/03 19:26:54, GvR wrote:
> Patch Set 2 is my new idea.
>
> Get rid of the __del__ on the Future, but add a small object "dangling off the
> side" that is guaranteed not to have any cycles (its only instance variable is
a
> list of strings). The __del__ on that side object will log those strings.
When
> the exception is requested through result() or exception() the side object is
> reset and removed.
i like the idea. some notices:
in constructor we should add:
Hack("Future abandoned before completion")
in set_result():
Hack("Future result has not been requested")
On Fri, May 3, 2013 at 12:35 PM, <fafhrd91@gmail.com> wrote: > i like the idea. ...
12 years, 6 months ago
(2013-05-03 20:56:17 UTC)
#6
On Fri, May 3, 2013 at 12:35 PM, <fafhrd91@gmail.com> wrote:
> i like the idea. some notices:
>
> in constructor we should add:
> Hack("Future abandoned before completion")
> in set_result():
> Hack("Future result has not been requested")
Hm... I'm not sure these matter all that much. I imagine that
abandoned Futures are pretty common -- it only becomes a problem when
an exception gets lost this way. The zen of Python says:
Errors should never pass silently.
Unless explicitly silenced.
That is the issue I am trying to solve here.
--
--Guido van Rossum (python.org/~guido)
Issue 9057046: Experimental solution for printing tracebacks more often
(Closed)
Created 12 years, 6 months ago by GvR
Modified 12 years, 6 months ago
Reviewers: Nikolay Kim, gvrpython
Base URL:
Comments: 0