python / asyncio

asyncio historical repository
https://docs.python.org/3/library/asyncio.html
1.04k stars 177 forks source link

How do I design coroutine with deep function calls? #442

Closed ironyee closed 7 years ago

ironyee commented 7 years ago
async def funcWithIO():
  await IORequest()

def func5():
  funcWithIO()

def func4():
  func5()

def func3():
  func4()

def func2():
  func3()

def func():
  func2()

I encountered a design issue. Let's suppose I transform funcWithIO to coroutine function for an asynchronous IO request. Because funcWithIO turn into coroutine function, func5 must become coroutine function even If there is no need to call funcWithIO asynchronously.

async def funcWithIO():
  await IORequest()

async def func5():
  funcWithIO()

async def func4():
  func5()

async def func3():
  func4()

async def func2():
  func3()

async def func():
  func2()

Return value of funcWithIO is a generator not any value. To call funcWithIO, I need some keywords await or yield. (If I wanna call functions as a normal function, I'll put a yield keyword before function calls.)

Fjnally, form of my code will become below without my intensions. Is this a normal situation?

async def funcWithIO():
  await IORequest()

async def func5():
  yield funcWithIO()

async def func4():
  yield func5()

async def func3():
  yield func4()

async def func2():
  yield func3()

async def func():
  yield func2()
ajdavis commented 7 years ago

You need to use await, rather than yield, in a native coroutine declared with async def.

Otherwise, your understanding is correct: a coroutine can only be called by another coroutine, not by a regular function. This is by design. So you're right, if funcWithIO is a coroutine then all the other functions in your call stack must also be coroutines.

ironyee commented 7 years ago

@ajdavis Thanks for your reply. I fully understand your comment.

If I use await, all coroutines are called asynchronously. In this way, It means a change of program machanism. So, will It be a very big problem? Not just a simple problem of readability.

ajdavis commented 7 years ago

Every function in your program that does network I/O must be written as a coroutine. If you have a large amount of code written already that does not use coroutines, then porting your code to asyncio and making it asynchronous might be a very large task.

Does that answer your question?