I like that the exceptions and constants are shared between the two modules; it expresses that the APIs are intended to look alike and the similarity isn't just a coincidence.
However, I don't like the dependency either (hence the TODO comment :-). When I introduced it I didn't realize there were platforms where concurrent.futures can't be imported. I would be fine with conditionally importing concurrent.futures and using the constants from it, and when it can't be imported, define the constants and exception classes locally. This could be put in a new submodule just for the purpose (to avoid having the conditional import logic in both futures.py and tasks.py). There is probably something you have to do to wrap_future() as well. However, that still leaves the use of a thread pool in run_in_executor() -- how else are you going to call getaddrinfo() in a separate thread? (Did you solve this in Trollius yet?) I would be okay with a private backport of a minimal executor for this purpose. Finally, on the one platform where concurrent.futures can't be imported, isn't it because it doesn't have threads? So even a private thread pool wouldn't solve the problem on that platform (though you could get a lot more tests to pass). I guess nothing would solve the problem on that platform except just calling getaddrinfo() in-line -- I suppose you could have a dummy thread pool that uses the dummy_threading stdlib module to minimize the conditional stuff you have to do in the Tulip code. On Thu, Jan 2, 2014 at 3:23 PM, Victor Stinner <[email protected]> wrote: > Hi, > > Many times, I was confused by the link between asyncio and > concurrent.futures modules. > > For example, on CPython FreeBSD 6.2 buildbot, concurrent.futures > module is missing, and so asyncio module cannot be imported. In my > opinion, this is a bug: you should be able to use callbacks and > coroutines without a pool of threads or processes. Another example is > my backport of asyncio on Python 2.x, I didn't understand why I had to > backport also concurrent.futures (by the way, there is a backport on > PyPI, I will reuse it). > > I found some references to concurrent.futures in asyncio source code. > > asyncio/futures.py: > --- > # TODO: Do we really want to depend on concurrent.futures internals? > Error = concurrent.futures._base.Error > CancelledError = concurrent.futures.CancelledError > TimeoutError = concurrent.futures.TimeoutError > --- > > asyncio/tasks.py: > --- > FIRST_COMPLETED = concurrent.futures.FIRST_COMPLETED > FIRST_EXCEPTION = concurrent.futures.FIRST_EXCEPTION > ALL_COMPLETED = concurrent.futures.ALL_COMPLETED > --- > > And BaseEventLoop.run_in_executor() creates a default executor (a pool > of threads) if none was defined. > > Is there a reason to reuse concurrent.futures exceptions and states > (string constants), except confusing me? :-) > > Victor -- --Guido van Rossum (python.org/~guido)
