添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
Generate a random integer between min and max Generating a random float between min and max Reverse the order of digits in a number Format large numbers with comma separators Convert a number to a byte array Calculate Exponents Strings The modern Python regular expressions cheat sheet The modern Python strings cheat sheet Find the length of a string String slicing Ways to format a string Remove leading/trailing whitespaces Reverse a string Check if a string contains a substring Concatenate strings Convert a string to lowercase/uppercase Convert a string into a list Declare a multiline string Capitalize the first letter of each word in a string Count the number of words in a string Check if a string is empty String replace() method Raw strings Compare 2 strings ignoring case sensitivity Remove one or many substrings from a string Remove all non-alphanumeric characters from a string Convert a string to a URL slug Convert a string to bytes and vice versa Convert a string to integer char codes Remove consecutive spaces Convert a string to binary codes Get the size of a string in bytes Convert a character to a code point and vice versa Base64 encode/decode a string in Python Add leading zeros to a string Check if a string is a valid URL Extract all URLs from text Get the filename and the file extension from a URL Get hostname, domain, and protocol from a URL Align a string Reverse the order of wrods in a string Get a list of unique words from a string Replace unwanted words in a string with asterisks Convert a string to a hexadecimal value Ways to generate random strings Count the frequency of each word in a string Generate random color codes Validate phone numbers Remove HTML tags from a string Unescape HTML entities from a string Remove empty lines from a string Validate an email address Control flow for loop While loop Conditional expression The WITH statement Try, except, else, finally The match/case statement Return multiple results from a function Keyword & positional arguments Lists Create a list List comprehension Access elements in a list Iterate through a list Count elements in a list Check whether a list is empty Replace/update elements in a list Combine lists Select random elements from a list Remove elements from a list Find all occurrences of a value in a list Reverse a list Find min and max in a numeric list Find the sum of a list Calculate the average of a numeric list List insert() method Sorting lists Create nested lists Flatten a nested list Clone a list Remove duplicates from a list Filter a list reduce() function Find common elements in 2 lists Swap 2 elements in a list Compare 2 lists Check if a list contains an element Shuffle a list Calculate the product of a numeric list Count the occurrences of elements in a list Iterate over 2 lists in parallel The map() function Divide a list into equally sized chunks Declaring lists with type hints Passing a list to a function as multiple arguments Generate a dummy list with N random elements List element-wise operations in Python IndexError: List index out of range Network & JSON Parsing JSON data Create JSON Data from a Dictionary Convert a list to JSON Send GET requests with aiohttp aiohttp POST requests Set timeouts when using aiohttp Download files with aiohttp streams aiohttp upload files aiohttp - send multiple requests concurrently Create a simple web server with aiohttp Use aiohttp to crawl webpages asynchronously Convert a dictionary to a query string Best open-source libraries to make HTTP requests System & File I/O File modes Date and Time Convert Datetime to Timestamp and vice versa Comparing 2 Dates Convert Date Strings into Date Objects Format Date and Time Check if a date string is valid Get the Current Date and Time with Timezone Get a list of dates between 2 dates Async & Await An introduction to coroutines and event loops asyncio.run() Async/await and loops asyncio.sleep() function asycnio.create_task() function asyncio.wait_for() function asyncio.gather() function async/await & timeouts loop.run_until_complete() Define and call async functions Handle exceptions Use the result returned by an async function asyncio.Runner() context manager asyncio.Semaphore class Running a function periodically with asyncio asyncio.wait() function asyncio.Queue class asyncio.as_completed() function Async generators (with "yield") run_coroutine_threadsafe() Using async/await with class methods Define a class with an async constructor asyncio.loop.run_in_executor() Run a task at a certain time time every day loop.create_server() method Add a coroutine to an already running event loop RuntimeWarning: Coroutine was never awaited CancelledError exception SyntaxError: 'await' outside async function Dataclasses Introduction to dataclass Defining Fields in Dataclass Using Dataclass Methods Using Inheritance with Dataclass How to Validate Data in Dataclass Set Default Values in Dataclass Using Class Decorators with Dataclass Fun Examples Get all links from a webpage with Beautiful Soup Extract plain text from a webpage Extract and download all images from a webpage 3 ways to hash a password Check System RAM/CPU/Disk Usage Schedule events with sched.scheduler class

Python asyncio.run_coroutine_threadsafe() function (with examples)

Updated: August 10, 2023 By: Khue Post a comment

The fundamentals

asyncio.run_coroutine_threadsafe() was added to the Python programming language in version 3.4.4. The function is used to submit a coroutine to a given event loop from another thread. It allows regular blocking code to make use of asyncio features, or to call blocking functions that have no async equivalent from the asyncio module.

Syntax & parameters

The syntax of the asyncio.run_coroutine_threadsafe() function is:

asyncio.run_coroutine_threadsafe(coro, loop)

Where:

  • coro : a coroutine object that will be executed in the event loop. It must be an awaitable object, such as a coroutine declared with the async keyword.
  • loop : an asyncio event loop object that will run the coroutine. It must be running in another thread, otherwise, the function will raise a RuntimeError .
  • The asyncio.run_coroutine_threadsafe() function returns a concurrent.futures.Future object that represents the result of the coroutine submitted to the event loop. This object is a blocking future, which means that you can call its result() method to wait for the coroutine to finish and get its return value. However, you should be careful not to call this method from the same thread as the event loop, as this will cause a deadlock. You can also use other methods of the Future object, such as add_done_callback() , cancel() , or exception() to interact with the coroutine.

    When and when NOT to use asyncio.run_coroutine_threadsafe()

    The asyncio.run_coroutine_threadsafe() function is really helpful in some situations:

  • When you are introducing asyncio into an existing large program (likely an old one) that uses threads and blocking calls and cannot be converted to asyncio all at once.
  • When you need to call blocking functions that have no async equivalent from asyncio , e.g. CPU-bound functions, legacy database drivers, and something like that.
  • If you’re starting a new project (that doesn’t involve blocking functions without async equivalent), there is no reason to use the asyncio.run_coroutine_threadsafe() function. Instead, it’s better to write the code entirely using asyncio features, such as coroutines, tasks, futures, and async/await syntax.

    At this point, you might get bored with concepts and boring words. It’s time to get our hands dirty with code.

    Examples

    Example 1: Welcome to Sling Academy (basic)

    This simple example shows you how to use the asyncio.run_coroutine_threadsafe() function to print “Welcome to Sling Academy!” from a coroutine in another thread:

    # SlingAcademy.com
    # This code uses Python 3.11.4
    import asyncio
    import threading
    # Define a coroutine
    async def welcome():
        await asyncio.sleep(2)
        print("Welcome to Sling Academy!")
        return "This is the result of the coroutine."
    # Define a function that runs the coroutine in a thread
    def run_in_thread(loop):
        # Submit the coroutine to the loop
        future = asyncio.run_coroutine_threadsafe(welcome(), loop)
        # Wait for the result
        print(f"Result: {future.result()}")
    if __name__ == "__main__":
        # Get the main event loop
        loop = asyncio.get_event_loop()
        # Create a thread that runs the coroutine
        thread = threading.Thread(target=run_in_thread, args=(loop,))
        # Start the thread
        thread.start()
        # Run the loop forever
        loop.run_forever()

    Output:

    Welcome to Sling Academy!
    Result: This is the result of the coroutine.

    Example 2: Fetching URLs (intermediate)

    In this example, we’ll use the asyncio.run_coroutine_threadsafe() function to fetch multiple URLs concurrently from a coroutine in another thread. We’ll use a library named requests to make network requests. You can install it by running:

    pip install requests

    The code:

    # SlingAcademy.com
    # This code uses Python 3.11.4
    import asyncio
    import requests
    import threading
    async def fetch_url(url):
        # Use requests library to get the content of the url
        response = requests.get(url)
        return response.content
    def run_in_thread(loop):
        # A list of urls to fetch
        urls = [
            "https://api.slingacademy.com",
            "https://api.slingacademy.com/v1/sample-data/photos",
            "https://api.slingacademy.com/v1/sample-data/users",
        # A list of futures to store the results
        futures = []
        # Submit each coroutine to the loop
        for url in urls:
            future = asyncio.run_coroutine_threadsafe(fetch_url(url), loop)
            futures.append(future)
        # Wait for all futures to complete
        for future in futures:
            # Print the length of each content
            print(len(future.result()))
    if __name__ == "__main__":
        # Get the main event loop
        loop = asyncio.get_event_loop()
        # Create a thread that runs the coroutine
        thread = threading.Thread(target=run_in_thread, args=(loop,))
        # Start the thread
        thread.start()
        # Run the loop forever
        loop.run_forever()

    Output:

    Example 3: Calling CPU-bound functions (advanced)

    This example demonstrates how to use the asyncio.run_coroutine_threadsafe() function to call a CPU-bound function (factorial) from a coroutine in another thread:

    # SlingAcademy.com
    # This code uses Python 3.11.4
    import asyncio
    import concurrent.futures
    import math
    import threading
    async def factorial(n):
        # Use concurrent.futures module to run the math.factorial function in a separate process
        with concurrent.futures.ProcessPoolExecutor() as pool:
            result = await loop.run_in_executor(pool, math.factorial, n)
            return result
    def run_in_thread(loop):
        # A list of numbers to calculate the factorial
        numbers = [5, 10, 20, 30]
        # A list of futures to store the results
        futures = []
        # Submit each coroutine to the loop
        for n in numbers:
            future = asyncio.run_coroutine_threadsafe(factorial(n), loop)
            futures.append(future)
        # Wait for all futures to complete
        for future in futures:
            # Print the result of each factorial
            print(future.result())
    if __name__ == "__main__":
        # Get the main event loop
        loop = asyncio.get_event_loop()
        # Create a thread that runs the coroutine
        thread = threading.Thread(target=run_in_thread, args=(loop,))
        # Start the thread
        thread.start()
        # Run the loop forever
        loop.run_forever()

    Output:

    3628800 2432902008176640000 265252859812191058636308480000000

    In this case, the asyncio.run_coroutine_threadsafe() function helps us perform a computation-intensive task that would block the event loop if done in the same thread.

    Afterword

    You’ve learned the fundamentals of the asyncio.run_coroutine_threadsafe() function in Python and seen its helpfulness in certain situations. Try to run all of the examples on your machine, modify some lines of code, and see what happens. This is a nice way to learn new things.

    This tutorial ends here. If you find something outdated or incorrect, please let me know by leaving a comment. Happy coding & have a nice day!

    Next Article: Python async/await and timeouts (with examples)

    Previous Article: Python asyncio.create_task() function (with examples) Series: Python Asynchronous Programming Tutorials