Python 3.8 将 for 循环转换为多处理/多线程

Aja*_*sra 3 python python-multithreading python-3.x python-multiprocessing

我是多重处理的新手,如果有人可以在这里指导/帮助我,我将非常感激。我有以下 for 循环,它从两个函数获取一些数据。代码看起来像这样

    for a in accounts:
        dl_users[a['Email']] = get_dl_users(a['Email'], adConn)
        group_users[a['Email']] = get_group_users(a['Id'], adConn)

    print(f"Users part of DL - {dl_users}")
    print(f"Users part of groups - {group_users}")
    adConn.unbind()

Run Code Online (Sandbox Code Playgroud)

这工作正常并获得所有结果,但最近我注意到它需要很多时间来获取用户列表,即 dl_users 和 group_users。大约需要 14-15 分钟才能完成。我正在寻找可以加速该函数的方法,并希望将此 for 循环转换为多处理。get_group_usersget_dl_users调用 LDAP,所以我不能 100% 确定是否应该将其转换为多处理或多线程。任何建议都会有很大帮助

Fed*_*o S 5

正如评论中提到的,多线程适用于 I/O 操作(从/向文件读取/写入、发送 http 请求、与数据库通信),而多处理适用于 CPU 密集型任务(例如转换数据、进行计算)。 ..)。根据您的函数执行的操作类型,您需要其中之一。如果他们进行混合,请在内部将它们分开并分析两者中的哪一个真正需要优化,因为多处理和线程都会带来可能不值得增加的开销。

也就是说,在最近的 Python 版本(包括 3.8)中应用多处理或多线程的方法非常简单。

多重处理

from multiprocessing import Pool


# Pick the amount of processes that works best for you
processes = 4

with Pool(processes) as pool:
    processed = pool.map(your_func, your_data)
Run Code Online (Sandbox Code Playgroud)

其中your_func是一个应用于 的每个元素的函数your_data,它是一个可迭代的。如果需要向可调用函数提供一些其他参数,可以使用 lambda 函数:

processed = pool.map(lambda item: your_func(item, some_kwarg="some value"), your_data)
Run Code Online (Sandbox Code Playgroud)

多线程

多线程的 API 非常相似:

from concurrent.futures import ThreadPoolExecutor


# Pick the amount of workers that works best for you.
# Most likely equal to the amount of threads of your machine.
workers = 4

with ThreadPoolExecutor(workers) as pool:
    processed = pool.map(your_func, your_data)
Run Code Online (Sandbox Code Playgroud)

your_data如果您想避免在需要项目的某些属性而不是项目本身时存储在内存中,则可以使用生成器:

processed = pool.map(your_func, (account["Email"] for account in accounts))
Run Code Online (Sandbox Code Playgroud)