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)

Reply via email to