【Python】Defining Asynchronous Functions (Coroutines) and Coroutine Objects

目次

Overview

This article explains the basic syntax for defining asynchronous functions using async def and the special return value called a “coroutine object.” Unlike regular functions (synchronous functions), a function defined with async def has a very important characteristic: the code inside is not executed just by calling the function.

Specifications (Input/Output)

  • Input: Calling a function defined with async def.
  • Output: An object of type coroutine (not the result of the process).
  • Syntax: async def function_name(arguments):

Basic Usage

To define an asynchronous function, add the async keyword before the function definition. When you call this function, it immediately returns a “coroutine object” as its return value.

import asyncio

# Defining an asynchronous function
async def my_coroutine():
    print("This message will not be displayed just by calling the function.")
    return "Finished"

# Calling the function
# The code inside the function is NOT executed yet!
obj = my_coroutine()

# Checking the type
print(type(obj))  # <class 'coroutine'>

Full Code

The following code demonstrates how a coroutine object is created and how to actually execute it to retrieve the result using asyncio.run.

import asyncio

# 1. Defining an asynchronous function (async def)
async def main_task(name):
    print(f"[{name}] Asynchronous function started")
    # Simulating an asynchronous process
    await asyncio.sleep(1)
    print(f"[{name}] Finished")
    return f"Result of {name}"

# --- Execution Check ---
if __name__ == "__main__":
    print("--- 1. Calling the function normally ---")
    # Calling it like a regular function
    coro = main_task("Test1")
    
    # The return value is not the result, but a "coroutine object"
    print(f"Return value type: {type(coro)}")
    print(f"Object content: {coro}")
    
    # Note: "Asynchronous function started" is not displayed yet.
    # If you leave an unexecuted coroutine, you may get a RuntimeWarning.
    coro.close() # Closing without executing

    print("\n--- 2. Executing with the event loop ---")
    # Execution begins only when passing the coroutine object to asyncio.run()
    result = asyncio.run(main_task("Test2"))
    
    print(f"Execution Result: {result}")

Customization Points

Coroutine Characteristics

The following table compares regular functions and asynchronous functions.

ItemRegular Function (def)Asynchronous Function (async def)
Keyworddef func():async def func():
When CalledExecuted immediately.Returns a coroutine object without executing.
Execution Methodfunc()await func() or asyncio.run(func())
Return ValueCalculated result.Calculated result (received after using await).

Important Notes

RuntimeWarning

If you create a coroutine object (e.g., obj = main()) but end the program without using await or asyncio.run(), Python will issue a RuntimeWarning stating that the coroutine was never awaited.

await Restrictions

The await keyword, which is used to wait for the result of an asynchronous function, can only be used inside functions defined with async def. Using await inside a regular function will result in a syntax error.

Summary

  • async def creates the “blueprint” of a coroutine.
  • Calling the function () creates a “task waiting to be executed” (coroutine object).
  • asyncio.run() or await actually performs the “execution.”

The fact that “calling” and “executing” are separate steps is the most significant feature of asynchronous processing in Python.

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次