如何在 multiprocessing.dummy.Pool 中单独命名线程?

Mat*_*att 6 python multithreading python-multithreading

我想命名 a 中的线程multiprocessing.dummy.Pool,以便当我threading.enumerate()从主线程调用时可以查看它们的所有名称。pool.apply_async当我调用能够命名线程时,是否可以应用关键字?我宁愿在创建时命名它们,而不是在tester函数内部命名,只是为了简洁。

例如,如果我有下面的示例代码:

import multiprocessing.dummy
from time import sleep
import threading

def tester():
    sleep(2)
    print("running \n")

def run_conc(number_of_threads, fxn):
    pool = multiprocessing.dummy.Pool(processes=number_of_threads)
    for thread in range(number_of_threads):
        pool.apply_async(tester)
    print(threading.enumerate(), "\n")
    pool.close()
    pool.join()

run_conc(3, tester)
Run Code Online (Sandbox Code Playgroud)

当我运行它时,我收到输出:

[<_MainThread(MainThread, started 140735632434048)>, <Thread(SockThread, started daemon 123145521917952)>, <DummyProcess(Thread-1, started daemon 123145527246848)>, <DummyProcess(Thread-2, started daemon 123145532502016)>, <DummyProcess(Thread-3, started daemon 123145537757184)>, <Thread(Thread-4, started daemon 123145543012352)>, <Thread(Thread-5, started daemon 123145548267520)>, <Thread(Thread-6, started daemon 123145553522688)>] 

running 
running 
running 
Run Code Online (Sandbox Code Playgroud)

我希望能够命名该线程列表中的 3 个虚拟线程,以便我可以识别哪个是哪个。或者也许有一种方法可以从内部做到这一点concurrent.futures,我应该使用它?

Dar*_*aut 5

池中的工作线程不是在您调用pool.apply_async或其他池方法时创建的,而是在您实例化池时已经创建的。对池方法的调用使用池中的现有线程。

如果不操作源,就无法在初始化时命名线程。您的选择是:

  • 池准备好实例化重命名工作线程
  • 猴子修补池内部以强制执行特定的命名模板

第一个选项很容易实现,您只需迭代._pool池实例的 - 属性并更改所.name包含线程的:

from multiprocessing.pool import ThreadPool as Pool


if __name__ == '__main__':

    pool = Pool(4)
    print([w.name for w in pool._pool])
    # ['Thread-1', 'Thread-2', 'Thread-3', 'Thread-4']

    for w in pool._pool:
        w.name = w.name.replace('Thread', 'ThreadPoolWorker')

    print([w.name for w in pool._pool])
    # ['ThreadPoolWorker-1', 'ThreadPoolWorker-2', 'ThreadPoolWorker-3', 'ThreadPoolWorker-4']

    pool.close()
    pool.join()
Run Code Online (Sandbox Code Playgroud)

请注意,我multiprocessing.pool.ThreadPool在这里使用,只是为了符合下面第二个选项中的示例,因为multiprocessing.dummy.Pool它只是ThreadPool.


对于第二个选项,可以使用ThreadPool.Process包装器修补工作线程的工厂函数,用更有意义的名称扩展默认名称“Thread-%d”(%d 填充计数器的值)像“ThreadPoolWorker”。

# threadpool.py
# Module patching the name of worker-threads within ThreadPool

__all__ = ['ThreadPool']

from functools import wraps
from multiprocessing.pool import ThreadPool


def rename_worker(fn):
    @wraps(fn)
    def wrapper(*args, **kwargs):
        w = fn(*args, **kwargs)
        w.name = w.name.replace('Thread', 'ThreadPoolWorker')
        return w
    return wrapper


ThreadPool.Process = staticmethod(rename_worker(ThreadPool.Process))
Run Code Online (Sandbox Code Playgroud)

用法:

from threadpool import ThreadPool as Pool


if __name__ == '__main__':

    pool = Pool(4)
    print([w.name for w in pool._pool])
    # ['ThreadPoolWorker-1', 'ThreadPoolWorker-2', 'ThreadPoolWorker-3', 'ThreadPoolWorker-4']
    pool.close()
    pool.join()
Run Code Online (Sandbox Code Playgroud)