Hello,
On Thu, 11 Jun 2015 04:36:42 -0700 (PDT)
Martin Teichmann <[email protected]> wrote:
> Hello,
>
>
> > And I personally
> > would have real hard time explaining people while read operation
> > should be called with "yield from" (or "await" soon), while its
> > counterpart write - without.
> >
>
> No. This is actually very simple and obvious: when you call read, you
> need the result of that to continue working, with write, you don't.
You just described why they *can* be different, not why they *have* to
be.
> So you need to wait for the former, but not for the latter.
Everything is relative. If data to read is already available and
buffered, you don't need to wait for it. And vice-versa, if there's
nowhere to buffer write data, you have to wait for buffer space to be
available.
> There simply is no symmetry between read and write when it comes
> to asyncio. This is like asking "why does write have a parameter
> data, while read doesn't?", well, because, they are different.
There's no limit in how different you can make 2 things (no matter how
similar they are). But the talk is about different direction - how to
make them similar and consistent.
> The entire coolness of asyncio lies in the fact that you clearly mark
> the places where concurrency enters. By making just everything a
> coroutine, this great idea just disappears.
No, it doesn't. Nobody want to deprive you of right to use sync write,
it stays where it was.
> And write is a very good
> example for this. Sometimes in my code I have two writes:
>
> writer.write("something")
> writer.write("else")
>
> because this is asyncio, I know that those two writes will be called
> directly after each other, and that the data goes out into the world
> just like that.
No, you can't. Almost no networking stack gives such guarantees, TCP/IP
for one doesn't (if we talk about message boundaries).
And then the same unguaranteedness is possible with async version:
yield from writer.async_write("something" + "else")
(replace with io.StringIO() per your needs).
> This is the large advantage over multi-threaded
> programming: there some other thread might write something
> in between those lines, and the result is just some mingled data.
Sorry, in the end, if you write to the same sink from 2 concurrency
primitives, be it 2 threads, or 2 coroutines, without synchronization
between them, you'll end up with a mess sooner or later. Most people
simply have one producer for one sink. But if you want to do tricks
like the above - ... you can keep doing them, as sync write stays where
it was. (But then how do you deal with read?)
> Sure, in multi-threaded programming I can just use mutexes. But
> you quickly run into large problems with hardly debuggable code.
>
> So in short: when designing an API for use with asyncio, try
> to limit the use of coroutines to where it is really, really
> necessary.
>
> Btw, is there anyone who could comment on my original posting,
> that StreamWriter.drain cannot be called concurrently?
Well, sorry for hijacking your thread. I kinda meant that async_write()
would certainly call fixed drain() ;-).
>
> Greetings
>
> Martin
--
Best regards,
Paul mailto:[email protected]