Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.Sign up
[discussion] Should functions like spawn take a coroutine object, or the classic fn+args+kwargs tuple? #122
async def my_async_function(...): ... curio.spawn(my_async_function(arg1, arg2))
This is fairly elegant and I'm not sure it's wrong, but I've run into a few situations where it's feeling a bit awkward, so I wanted to raise for the discussion the possibility that they should instead take an async callable + arguments:
curio.spawn(my_async_function, arg1, arg2)
The arguments for taking a callable:
The arguments against taking a callable:
On 11/20/16, Nathaniel J. Smith firstname.lastname@example.org wrote:
spawn(co) is much better. Control over the creation and manupulation
I dont think it is an important reason. Current form is also handy.
It is the awkwardness of Python.
It is the nature of such functions. Like calling threads. No better solution
I think no generalization is possible for all cases. That's why we
OK. But, I mean... I liked the current approach too, until I started using it more and started running into some issues. Obviously it's your project and you don't owe me anything, but I admit it's a bit frustrating to write down some concrete analyses of the issues and then get two replies that brush these aside without engaging with the trade-offs.
Sorry. Didn't mean to be curt--I'm often very scattered for time with kids and other things going on. I've been meaning to get back here. A few thoughts...
I like the current approach because it is extremely minimal and simple. You provide a coroutine and curio runs it. One of my major complaints with asyncio is that it is just too complicated for me to remember how to do anything. Getting the event loop. A about a half-dozen methods all related to running things, all slightly different. I don't like it. Saying
I also like the current approach because it is easy to have optional keyword arguments attached to the
I must admit that the fact that coroutines don't immediately evaluate until awaited is something that takes some getting used to though. There are all sorts of crazy ways of passing them around in an unevaluated state and then doing things later.
So, I was recently doing a bunch of coding involving Curio and threads. You're right, the calling conventions are different. Naturally this issue makes it impossible to "unsee" the difference. I'm not entirely sure I'm going to do anything about it (yet), but I see what you mean here. Need to think about it more.
Confession: I'm still thinking about this issue. You're absolutely right, there is an inconsistency here. There are a couple of different ways of spawning work in Python (in the library).
There are threads:
There is multiprocessing:
And there are executors (from concurrent.futures):
Asyncio has a
If you want keyword arguments, you'd have to partial it:
Of these, I personally like the
Getting back to
I could make
I'm just not sure what to do with additional keyword arguments to
Or there could simply be "reserved" keyword arguments to curio recognizes and that you'd have to avoid in called code.
Anyways, I'm still thinking about this. Wondering if anyone has any renewed ideas about it here.
Apart from consistency what exactly we will gain from this?
co = cofunc(...)
Infact on the contrary bringing such a convention to
pco = Process(...)
I remember we also had been talking about
Basically, it's just consistency. It's not an entirely unimportant thing in my experience, but maybe it's impossible to get right in all cases. I was just thinking that if
It's a minor thing, but I've found myself mostly sticking to using the context manager forms of the timeout commands anyway. I could see an argument for making that the One Way to do it, just to simplify things a bit.…
On Dec 27, 2016 3:57 PM, "David Beazley" ***@***.***> wrote: Basically, it's just consistency. It's not an entirely unimportant thing in my experience, but maybe it's impossible to get right in all cases. I was just thinking that if spawn() changed, then you might also turn to changing functions such as timeout_after() as well. Hmmm. Now I'm not so sure. — You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub <#122 (comment)>, or mute the thread <https://github.com/notifications/unsubscribe-auth/AAlOaC6FzUaYU2FJ8zq1KZokFbwPiZC7ks5rMaXwgaJpZM4K3eXs> .
Wait... How didn't I see it?
pco = Process/Thread(...)
Of course it is meaningful: It is equivalent to launching
Anyway currently we don't have much api to control and
As we make progress on them lets keep this issue alive..
I've continued to think about this issue for awhile. Curio has grown some new functions for launching processes, performing work, and so forth. Some consistency is order. I'm going to modifiy curio to use a common signature for "launching" work whether it be a task, a thread, a process, or whatever:
Keyword arguments, if any, are reserved for options related to
Because of some backwards compatibility concerns with existing code, passing an instantiated coroutine to certain functions (spawn, run, etc.) will still work. However, documentation and examples will prefer the new approach.
I have modified curio to fairly universally adopt an API such as:
The older API such as:
will continue to work however. Basically, you can either pass an instantiated coroutine or a callable with arguments will be executed to produce a coroutine.