Setting a custom EventLoop

248 views
Skip to first unread message

Paul Tagliamonte

unread,
Jan 29, 2014, 11:30:34 PM1/29/14
to python...@googlegroups.com
Hey folks,

I love asyncio so far, nice work, huge step forward!

Running the following minimal example:

/
| import asyncio
| from asyncio.base_events import BaseEventLoop
|
|
| class TestEventLoop(BaseEventLoop):
| def something_important(self, arg):
| # Do something important with arg.
| pass
|
|
| def print_and_repeat(loop):
| print('Hello World')
| loop.call_later(2, print_and_repeat, loop)
|
|
| asyncio.set_event_loop(TestEventLoop())
|
|
| loop = asyncio.get_event_loop()
| loop.call_soon(print_and_repeat, loop)
| loop.run_forever()
\

Results in the following traceback:

/
| Traceback (most recent call last):
| File "test.py", line 21, in <module>
| loop.run_forever()
| File "/usr/lib/python3.4/asyncio/base_events.py", line 153, in run_forever
| self._run_once()
| File "/usr/lib/python3.4/asyncio/base_events.py", line 614, in _run_once
| event_list = self._selector.select(timeout)
| AttributeError: 'TestEventLoop' object has no attribute '_selector'
\

it appears there's some magic before actually setting the event loop.

What's the proper way to set the event loop? I really don't want to
re-implement the entire EventLoop class, I just want to add a few
methods for a quirky usecase I have.

Thanks, folks!

Cheers,
Paul

--
#define sizeof(x) rand()
</paul>
:wq
signature.asc

Guido van Rossum

unread,
Jan 30, 2014, 1:50:31 AM1/30/14
to Paul Tagliamonte, python-tulip
On Wed, Jan 29, 2014 at 8:30 PM, Paul Tagliamonte <pau...@gmail.com> wrote:
I love asyncio so far, nice work, huge step forward!

Thanks!
 
Running the following minimal example:

/
| import asyncio
| from asyncio.base_events import BaseEventLoop

You most likely shouldn't be doing this. That class is not a complete implementation, just a base with some parts of the implementation that is widely shared. The rest of the implementation is in various subclasses whose name isn't published -- and *which* class is used is determined dynamically at run time (either by the app or by the event loop policy).
 
|
| class TestEventLoop(BaseEventLoop):
|     def something_important(self, arg):
|         # Do something important with arg.
|         pass
|
|
| def print_and_repeat(loop):
|     print('Hello World')
|     loop.call_later(2, print_and_repeat, loop)
|
|
| asyncio.set_event_loop(TestEventLoop())
|
|
| loop = asyncio.get_event_loop()
| loop.call_soon(print_and_repeat, loop)
| loop.run_forever()
\

Results in the following traceback:

/
| Traceback (most recent call last):
|   File "test.py", line 21, in <module>
|     loop.run_forever()
|   File "/usr/lib/python3.4/asyncio/base_events.py", line 153, in run_forever
|     self._run_once()
|   File "/usr/lib/python3.4/asyncio/base_events.py", line 614, in _run_once
|     event_list = self._selector.select(timeout)
| AttributeError: 'TestEventLoop' object has no attribute '_selector'
\

it appears there's some magic before actually setting the event loop.

There's nothing wrong with your set_event_loop() call, just with your event loop class...
 
What's the proper way to set the event loop? I really don't want to
re-implement the entire EventLoop class, I just want to add a few
methods for a quirky usecase I have.

 Does what you want to add *have* to be an event loop method? If you make it a function that takes a loop argument you don't have to deal with the subclassing.

If you really can't do it any other way, and you really need to inherit from the event loop, you can inherit from asyncio.SelectorEventLoop, which is an alias for the real selector-based event loop (the concrete class varies by platform). But then you won't be supporting IOCP on Windows. And you probably shouldn't get too comfortable doing that.

--
--Guido van Rossum (python.org/~guido)

Paul Tagliamonte

unread,
Jan 30, 2014, 8:08:32 AM1/30/14
to Guido van Rossum, python-tulip
On Wed, Jan 29, 2014 at 10:50:31PM -0800, Guido van Rossum wrote:
>
> You most likely shouldn't be doing this. That class is not a complete
> implementation, just a base with some parts of the implementation that is
> widely shared. The rest of the implementation is in various subclasses whose
> name isn't published -- and *which* class is used is determined dynamically at
> run time (either by the app or by the event loop policy).

Hurm, gotcha.

> There's nothing wrong with your set_event_loop() call, just with your event
> loop class...

Figured :)

> What's the proper way to set the event loop? I really don't want to
> re-implement the entire EventLoop class, I just want to add a few
> methods for a quirky usecase I have.
>
>
>  Does what you want to add *have* to be an event loop method? If you make it a
> function that takes a loop argument you don't have to deal with the
> subclassing.

Yeah. I wanted to allow for something like (sorry, coding in my MUA, I don't
know if this even runs, just sketching it out)


| class EventedEventLoop(BaseEventLoop):
| _handlers = defaultdict(list)
|
| def add_event_handler(self, event, function):
| self._handlers[event].append(function)
|
| def fire_event(self, event, *args):
| for handler in self._handlers[event]:
| self.call_soon(handler, *args)

So, yeah, I can do this another way, I can just drop that defauldict out
and change `self' to `loop' and I'm gold.

I hate the syntatic cruft that pops up with that way (looks messier),
but I think I might be able to life with myself :)

> If you really can't do it any other way, and you really need to inherit from
> the event loop, you can inherit from asyncio.SelectorEventLoop, which is an
> alias for the real selector-based event loop (the concrete class varies by
> platform). But then you won't be supporting IOCP on Windows. And you probably
> shouldn't get too comfortable doing that.

Yeah, gotcha. I'm sure I'll stumble into something cleaner. Perhaps I'll
wrap the `loop' class and see if I can't hide this hackyness away :)

> --
> --Guido van Rossum (python.org/~guido)

Thanks, Guido!
signature.asc
Reply all
Reply to author
Forward
0 new messages