asyncio event_loop declared outside of a class with asyncio.coroutine methods fails with "AttributeError: 'NoneType' object has no attribute 'select'"

class, python

Solution

As it turns out, the issue was with the context of the event loop.

`asyncio` magically creates an event loop for a thread at runtime. This event loop's context is set when `.get_event_loop()` is called.

In the above example, `a.run_loop` sets the event loop inside the context of `Foo.run_loop`.

One kicker of event loops is that there may only be one event loop per thread, and a given event loop can only process events in its context.

With that in mind, note that the `loop = asyncio.get_event_loop()` just after `a.run_loop` is asking to assign the thread's event loop to the `__main__` context. Unfortunately, the event loop was already set to the context of `Foo.run_loop`, so a `None` type is set for the `__main__` event loop.

Instead, it is necessary to create a new event loop and then set that event loop's context to `__main__`, i.e.

new_loop = asyncio.new_event_loop()
asyncio.set_event_loop(new_loop)

Only then will an event loop be properly set in the context of `__main__`, allowing for the proper execution of our now-modified `new_loop.run_until_complete(a.call_as())`

Problem

Exploring Python 3.4.0's asyncio module, I am attempting to create a class with asyncio.coroutine methods that are called from an event_loop outside of the class. My working code is below. ``` import asyncio class Foo(): @asyncio.coroutine def async_sleep(self): print('about to async sleep') yield from asyncio.sleep(1) @asyncio.coroutine def call_as(self): print('about to call ass') yield from self.async_sleep() def run_loop(self): loop = asyncio.get_event_loop() loop.run_until_complete(self.call_as()) print('done with loop') loop.close() a = Foo() a.run_loop() loop = asyncio.get_event_loop() loop.run_until_complete(a.call_as()) ``` The call to `a.run_loop()` provides output as expected: ``` python3 async_class.py about to call ass about to async sleep done with loop ``` However as soon as the event_loop attempts to process `a.call_as()` I get the following Traceback: ``` Traceback (most recent call last): File "async_class.py", line 26, in <module> doop.run_until_complete(asyncio.async(a.call_ass())) File "/opt/boxen/homebrew/opt/pyenv/versions/3.4.0/lib/python3.4/asyncio/base_events.py", line 203, in run_until_complete self.run_forever() File "/opt/boxen/homebrew/opt/pyenv/versions/3.4.0/lib/python3.4/asyncio/base_events.py", line 184, in run_forever self._run_once() File "/opt/boxen/homebrew/opt/pyenv/versions/3.4.0/lib/python3.4/asyncio/base_events.py", line 778, in _run_once event_list = self._selector.select(timeout) AttributeError: 'NoneType' object has no attribute 'select' ``` I have attempted wrapping `a.call_as()` in an `asyncio.Task()`, `asyncio.async()` and the failure is the same.

Original source