2014-05-23 8:54 GMT+02:00 Saúl Ibarra Corretgé <[email protected]>:
> Let me try to explain again :-) Assume I have a FooApp thing that
> works with both trollius and it's designed to be Python 2 and 3
> compatible. This application wants to use aiodns now. aiodns doesn't
> have a dependency on Python 3 or asyncio because it returns Future
> objects, so it doesn't matter if I import Future from asyncio or
> trollius. It does matter to FooApp, however.
>
> If FooApp is running on Python 3.4, it will still use trollius, but
> when importing aiodns, it will import asyncio in turn. Not necessarily
> a bad thing, but the Future objects returned by aiodns are
> asyncio.Future, and I don't think that will work when doing yield From
> or run_until_complete in trollius, will it?
Oh ok, it's more complex than what I understood :-)
I see 4 cases:
(a) Application written for asyncio (or Tulip): Python 3.3+
(b) Application written for Trollius: Python 2.6+
(c) Application able to use asyncio or Trollius, prefer asyncio: Python 2.6+
- python 2.6-3.2: use Trollius, or ImportError if Trollius is not installed
- python 3.3: use Tulip, or Trollius, or ImportError if none is installed
- python 3.4+: use asyncio of the stdlib
(d) Application able to use asyncio or Trollius, prefer Trollius: Python 2.6+
- python 2.6-3.2: use Trollius, or ImportError if Trollius is not installed
- python 3.3: use Trollius, or Tulip, or ImportError if none is installed
- python 3.4+: use Trollius, or Tulip, or use asyncio of the stdlib
Well, the problem is not really with a single application. The problem
is when a module doesn't use the same async library that the
application!
Use cases:
(1) Application and module uses asyncio (or Tulip)
(2) Application and module uses Trollius
(3) Application uses Trollius, module uses asyncio (or Tulip)
(4) Application uses asyncio (or Tulip), module uses Trollius
The cases (1) and (2) should work without any issue. The problem is
really when application and modules use different async modules, cases
(3) and (4).
My short test (see attached saul.py script) shows me that asyncio and
trollius don't understand them:
- It's not possible to set set an asyncio event loop in Trollius, same
error for the opposite.
- In debug mode, asyncio.async(<a trollius coroutine object>) raises a
TypeError because asyncio checks for asyncio.Future type, not
trollius.Future
- When using an asyncio event loop, Trollius coroutine complains that
the Return object was used without raise. The Trollius event loop sets
the raised attribute of Return, whereas the asyncio loop doesn't.
- I didn't spend much time on my test, there are probably much more issues.
Maybe Trollius should try to cooperate with asyncio when asyncio is
available on the system? For example, inherit asyncio classes (but
override methods) instead of using a new hierachy of classes?
Victor
import asyncio
import trollius
import dis
LOOP = 'asyncio'
#LOOP = 'trollius'
def aiodns_done(fut):
print(fut, "is done")
@trollius.coroutine
def aiodns(loop):
#fut = trollius.Future()
fut = trollius.Future(loop=loop)
print("fut.loop:", fut._loop)
fut.add_done_callback(aiodns_done)
loop.call_soon(fut.set_result, 42)
if LOOP == 'trollius':
loop = trollius.get_event_loop()
#asyncio.set_event_loop(loop)
else:
loop = asyncio.get_event_loop()
#trollius.set_event_loop(loop)
print("event loop:", loop)
coro = aiodns(loop)
if LOOP == 'trollius':
trollius.async(coro, loop=loop)
else:
asyncio.async(coro, loop=loop)
try:
loop.run_forever()
except KeyboardInterrupt:
print("exit (CTRL+c)")
finally:
print("close")
loop.stop()
loop.close()