On 25 April 2014 19:05, Paul Sokolovsky <[email protected]> wrote:

> Hello,
>
> On Fri, 25 Apr 2014 18:07:02 +0100
> Gustavo Carneiro <[email protected]> wrote:
>
> []
>
> > > So, the main question which remains is: How an instantiation of
> > > object may have such a strong side effect? Why such an object is
> > > modestly called Task, and not
> > > SelfSchedulingTaskViolatingExplicitIsBetterThanImplicitPrinciple?
> > >
> > > Actually, my first question was: is it ever documented somewhere?
> > > And re-reading asyncio docs, I found a proverbial example of
> > > fineprint. So, there's section "18.5.2.4.
> > > Task" (https://docs.python.org/3.4/library/asyncio-task.html#task),
> > > it has subsection "18.5.2.4.1. Example: Parallel execution of
> > > tasks". From the name it's clear that the subsection contains just
> > > an example and commentary to it. So, after a long example block, in
> > > very last short line of the subsection - a place where few people
> > > will pay enough attention to it, I found that sacral phrase - "A
> > > task is automatically scheduled for execution when it is created.
> > > The event loop stops when all tasks are done."
> > >
> > >
> > Because the whole point of Task is to be scheduled for execution, it
> > makes no sense to instantiate a Task and then have to call a separate
> > method the schedule it.
>
> What a fresh perspective! Indeed, why not take all objects and make
> them do "the most expected action" by default right away. Why all those
> messy methods on Popen - it can just slurp any output on construction
> and terminate the child process, HttpRequest can do a GET and slurp
> entire response, etc.
>

Actually Popen is a good example.  When you instantiate a Popen object, the
subprocess is launched immediately, event before the Popen object is
returned to the caller.  If you want to do any additional setup, you can
optionally pass a preexec_fn parameter.  This parameter is optional because
it is so rarely needed.  It makes sense that Popen launches a subprocess
directly because that's what it is there to do, it's obvious.


>
> > If you do not want to schedule it _right
> > now_ then what is the point of creating the Task in the first place?
>
> Because asyncio forces me! Advertised as native Python async framework,
> it doesn't even allow to use directly native Python coroutines, and
> instead appears to be attempt to marry Twisted and Node.JS, with native
> Python features being second-class citizens requiring being disguised
> into those projects' stuff, which has questionable traits, hinting of
> its heritage.
>

I do not know what you mean by "native Python coroutines".  As far as I'm
aware, there are no "native" Python coroutines.  Natively, Python has
generator functions.  Asyncio is a library that creates an illusion of
co-routine on top of generator functions.

If you are complaining about whether or not Python should have native
coroutines, with deep integration with the language itself, then I think
that discussion is out of scope for this list.


>
> > I suspect your expectactions are tainted by the previous knowledge of
> > the threading API, which has a separate Thread.start() method.  I
>
> My expectations are "tainted" by: 1) basic programming rule of thumb
> that you first initialize things properly, and then execute them; 2)
> intuitive feeling, and even explicit knowledge, of Python's "explicit is
> better than implicit" principle; 3) acquaintance (cursory, I have to
> admit) with many-year history of using generators/coroutines for async
> cooperative multitasking, and desire to use that using standardized API
> asyncio promotes.
>

As I said, Task is not executed immiediately upon instantiation, it is
merely _scheduled_ to be executed as soon as you return control to the main
loop.  You have plenty of opportunity to initialize things before the task
is executed.


> > think it makes _some_ sense that Thread objects do not start the
> > actual thread automatically, since threads are preemptive and prone
> > to race conditions, and you may want to store the Thread object in
> > some data structure _before_ the thread actually begins executing.
> > With asyncio.Task, even if the task is scheduled to be executed, it
> > is guaranteed not to be executed until you reach "yield from"
> > statement, so you have plenty of opportunity to any setup prior to
> > the task executing.
>
> Let's sum up what you're saying here: asyncio Task implementation, by
> relying on internal asyncio implementation details (so, naive users
> who will get fixation on such behavior will fail miserably in other
> contexts), violates "Explicit is better than implicit" principle *just
> because it can* ?
>

I'm not sure what you mean.

I suspect you want to do something clever and non-standard with Task and
asyncio, and are facing an obstacle due to the way Task schedules itself
for execution.  I believe this is what normal asyncio users want.  If you
are trying to achieve something "less normal", maybe you can work with the
Tulip maintainers to allow instantiating a Task without it being
automatically scheduled for execution.  For instance, by adding a keword
parameter to the constructor:

    Task(mygenerator(), schedule_for_execution=False)

Regards,

-- 
Gustavo J. A. M. Carneiro
Gambit Research
"The universe is always one step beyond logic." -- Frank Herbert

Reply via email to