0

Yield from coroutine vs yield from task In this link, there is an example give by @dano that:

import asyncio

@asyncio.coroutine
def test1():
    print("in test1")


@asyncio.coroutine
def dummy():
    yield from asyncio.sleep(1)
    print("dummy ran")


@asyncio.coroutine
def main():
    test1()
    yield from dummy()

loop = asyncio.get_event_loop()
loop.run_until_complete(main())

The output is only

dummy ran

I can't add comment to that directly, so I have to ask a new question here; (1) why the test1() isn't executed in order in such corutine function. Whether corutine can only use the following two ways?

yield from cor()
asyncio.async(cor())

Where did test1() go?

(2) There is also some other problems in understanding the differnence of the followng two methods to use corutine() function. Are they the same?

yield from asyncio.async(cor())
asyncio.async(cor())

I use the following code to explain:

import random
import datetime
global a,b,c
import asyncio

a = [random.randint(0, 1<<256) for i in range(500000)]  
b= list(a)
c= list(a)


@asyncio.coroutine
def test1():
    global b
    b.sort(reverse=True)
    print("in test1")


@asyncio.coroutine
def test2():
    global c
    c.sort(reverse=True)
    print("in test2")


@asyncio.coroutine
def dummy():
    yield from asyncio.sleep(1)
    print("dummy ran")

@asyncio.coroutine
def test_cor():
    for i in asyncio.sleep(1):
        yield i

@asyncio.coroutine
def main():
    test1()
    print("hhhh_______________________")
    asyncio.async(test1())
    asyncio.async(test2())
    print("hhhh_______________________")
    print("hhh")

    asyncio.async(dummy())
    yield from test_cor()

loop = asyncio.get_event_loop()
loop.run_until_complete(main())
print("hhhhhhh")

However the output is

hhhh_______________________
hhhh_______________________
hhh
in test1
in test2
hhhhhhh

It even didn't execute the dummy() function !

And I use

@asyncio.coroutine
def test2():
    # global c
    # c.sort(reverse=True)
    print("in test2")

(3) without sorting and I think test2 should run faster so that test1 is output after test2. However, the output didn't change. I don't know why.

(4)And I also tried to remove sorting for both test1() and test2(), then amazingly, dummy() runs and output the following. Why ??

hhhh_______________________
hhhh_______________________
hhh
in test1
in test2
dummy ran
hhhhhhh

I don't know how these things happens....I am relly bewilerded.

Ye Zhang
  • 13
  • 4
  • You need to use ` yield from`. – dirn Aug 19 '19 at 16:12
  • Does ```yield from test1()``` and ```asyncio.async(test1()) ``` the same ? – Ye Zhang Aug 19 '19 at 16:14
  • What's the executing order of ``` print("hhh"); yield from cor();``` It will ```print``` first right ? So why do we usually use corutine function since the normally they exectued in order. – Ye Zhang Aug 19 '19 at 16:20
  • Calling a coroutine doesn't execute it. You need to await it (`yield from` in the case of 3.4 syntax). – dirn Aug 19 '19 at 16:35
  • So ```yield from task``` will suspend it and open a new thread for it right? So the task can be run in parallel – Ye Zhang Aug 19 '19 at 16:40
  • asyncio doesn't use threads and tasks don't execute in parallel. – dirn Aug 19 '19 at 16:42
  • But the link I mentioned in another link said so. https://stackoverflow.com/questions/27076577/yield-from-coroutine-vs-yield-from-task – Ye Zhang Aug 19 '19 at 16:46
  • I see some comparisons to using threads, but there's no mention of asyncio using threads. – dirn Aug 19 '19 at 17:12
  • So is there any parallism inside? – Ye Zhang Aug 19 '19 at 17:14
  • No. asyncio uses cooperative multitasking. Only one task can execute at a time. A task can be suspended to allow another to execute while it is waiting (eg, for a response from a network call). – dirn Aug 19 '19 at 17:24
  • I update my question above. So the coruntine will be executed anyway right? But in my undated question, I run the code and asyncio.async(dummy()) doesn't even run. – Ye Zhang Aug 19 '19 at 17:27
  • `test1` does nothing to yield execution to `test2` so the latter won't start running until the former completes. And I believe you need to consume `test_cor` as a generator if you want it to yield execution back to `dummy` (or remove the `yield` so it can execute normally). – dirn Aug 19 '19 at 17:37
  • What's the meaning of consume `test_cor` as a generator ? I use `yield from test_cor()` and I think it's a way of using `test_cor()` as a generator.....(Also, why not add an answer to this question directly :) It will be easier to be accepted... – Ye Zhang Aug 19 '19 at 17:45
  • In the body of `test_cor` you use `yield`. Generators don't begin execution until you consume them. Replace `test_cor`'s entire body with `yield from asyncio.sleep(1)` and then you should see `dummy` execute. – dirn Aug 19 '19 at 17:56
  • I still didn't see dummy.....I have replaced the whole body. – Ye Zhang Aug 19 '19 at 18:32
  • If I use `yield from asyncio.async(dummy())` I can see dummy execute. But I can use `yield from asyncio.async(dummy())` to see dummy execute even I don't replace the whole body.... – Ye Zhang Aug 19 '19 at 18:33
  • Is there any difference between `yield from asyncio.async(dummy())` and `yield from dummy()` ? – Ye Zhang Aug 19 '19 at 18:41
  • With the `yield from`, no. Without it, yes. Without it `main` completes before `dummy` finishes and the loop is suspended. With it, `main` is blocked until `dummy` completed. – dirn Aug 20 '19 at 01:20

0 Answers0