简体   繁体   English

如何在多线程环境下运行 Python 代码?

[英]How to run Python code in multithreading environment?

I'm trying to execute the code on Python in parallel using asyncio .我正在尝试使用asyncio并行执行 Python 上的代码。 The idea is to run multiple jobs in parallel.这个想法是并行运行多个作业。

Here is my code:这是我的代码:

import asyncio
import threading

async def print_thread():
    for n in range(5):
        print("Number: {}".format(threading.get_ident()))

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    try:
        loop.run_until_complete(print_thread())
    finally:
        loop.close()

The output is: output 是:

Number: 4599266752
Number: 4599266752
Number: 4599266752
Number: 4599266752
Number: 4599266752

As far as I understand the code has been executed on a single thread.据我了解,代码已在单个线程上执行。 Is there a way to parallelize it?有没有办法并行化它?

PS附言

If I change the code to:如果我将代码更改为:

async def print_thread():
    print("Number: {}".format(threading.get_ident()))


if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    try:
        for n in range(5):
            loop.run_until_complete(print_thread())

I get the same result.我得到相同的结果。

Your for loop is inside your coroutine, so it cannot be in different threads.for循环在你的协程内,所以它不能在不同的线程中。 But even if you put the loop outside of your async function it will still run in the same thread:但即使你把循环放在你的异步 function 之外,它仍然会在同一个线程中运行:

import asyncio
import threading


async def print_thread():
    print("Thread: {}".format(threading.get_ident()))


if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    tasks = []
    for i in range(10):
        tasks.append(asyncio.ensure_future(print_thread()))
    loop.run_until_complete(asyncio.gather(*tasks))
    

Which will still output the same id:其中仍将 output 相同的 id:

Thread: 140366741292864
Thread: 140366741292864
Thread: 140366741292864
Thread: 140366741292864
Thread: 140366741292864
Thread: 140366741292864
Thread: 140366741292864
Thread: 140366741292864
Thread: 140366741292864
Thread: 140366741292864

The solution is to use a ThreadPoolExecutor , but it needs a function, not a coroutine, so you have to remove async from the definition:解决方案是使用ThreadPoolExecutor ,但它需要一个 function,而不是协程,因此您必须从定义中删除async

import asyncio
import threading
import concurrent.futures


def print_thread():
    print("Thread: {}".format(threading.get_ident()))


if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    with concurrent.futures.ThreadPoolExecutor() as pool:
        for i in range(10):
            loop.run_in_executor(pool, print_thread)

Which outputs:哪个输出:

Thread: 140446369556224
Thread: 140446361163520
Thread: 140446369556224
Thread: 140446361163520
Thread: 140446369556224
Thread: 140446352508672
Thread: 140446361163520
Thread: 140446344115968
Thread: 140446369556224
Thread: 140446335723264

As you can see, there are less threads than calls, it's normal.如您所见,线程比调用少,这是正常的。 But if you have large batchs, you can change the thread count with max_workers parameter in ThreadPoolExecutor constructor.但是如果你有大批量,你可以在ThreadPoolExecutor构造函数中使用max_workers参数来改变线程数。

If you still want to use a coroutine, there is a solution there: https://stackoverflow.com/a/46075571/7414475如果你仍然想使用协程,这里有一个解决方案: https://stackoverflow.com/a/46075571/7414475

Another answer with result collection, as requested in comments:根据评论中的要求,结果收集的另一个答案:

import asyncio
import threading
import concurrent.futures


def get_thread():
    return "Thread: {}".format(threading.get_ident())


if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    with concurrent.futures.ThreadPoolExecutor() as pool:
        tasks = []
        for i in range(10):
            tasks.append(loop.run_in_executor(pool, get_thread))
        print(loop.run_until_complete(asyncio.gather(*tasks)))

Output: Output:

['Thread: 139740266125056', 'Thread: 139740266125056', 'Thread: 139740266125056', 'Thread: 139740183525120', 'Thread: 139740266125056', 'Thread: 139740175132416', 'Thread: 139740183525120', 'Thread: 139740166739712', 'Thread: 139740266125056', 'Thread: 139740158347008']

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM