Python multiprocessing.Process()如何知道要打开多少个并发进程?

时间:2014-07-22 17:23:12

标签: python multithreading parallel-processing multiprocessing

我正在运行脚本来获取数据库表的列表,检查每个表的行数,并将每个查询的结果附加到字典中。我使用多处理来加快它的速度:Manager创建一个可共享的列表和可共享的字典,进程可以从中读取和追加,以及Process来设置进程。

from multiprocessing import Process, Manager

def main():
    mgr = Manager()
    # Function to get the list of tables
    table_list = mgr.list(get_table_list())

    counts = mgr.dict()
    for table in table_list:
        # get_table_count runs a 'SELECT COUNT(*) FROM <table>' and appends
        # the result to the counts dict
        p = Process(target=select_star, args=(table, counts, 'prod'))
        p.start()
        p.join()

我的问题是,Process如何管理开放流程的数量?我习惯于将pool()与apply_async()方法一起使用,您可以在其中指定实例化池时的进程数。

如果这是用于此应用程序的最佳方法的任何其他评论,也将不胜感激。

-

感谢dano帮助实施以下两种解决方案:

1 - 使用Pool.apply_async,因为我已经习惯了:

from multiprocessing import Process, Manager, cpu_count
def main():
    mgr = Manager()

    table_list = get_table_list()
    pool = Pool(cpu_count() / 2)

    prod_counts = mgr.dict()

    for table in table_list:
        pool.apply_async(get_table_count, args=(table, prod_counts, 'prod'))
    pool.close()
    pool.join()

2 - 使用带有itertools.partial()

的Pool.map()
from multiprocessing import Process, Manager, cpu_count
def main():
    mgr = Manager()

    table_list = get_table_list()
    pool = Pool(cpu_count() / 2)

    prod_counts = mgr.dict()
    func = partial(get_table_count, result_dict=prod_counts, env='prod')
    pool.map(func, table_list)

    print prod_counts

2 个答案:

答案 0 :(得分:2)

multiprocessing.Process不知道有多少其他进程是打开的,或者做任何事情来管理正在运行的Process个对象的数量。您需要使用multiprocessing.Pool来获取该功能。

如果直接使用Process,则在致电p.start()后立即启动子流程,并在致电Process时等待p.join()退出。因此,在您的示例代码中,您一次只运行一个进程,但是启动len(table_list)个不同的进程。

这不是一个好方法;因为你一次只启动一个进程,所以你并没有真正同时做任何事情。由于启动子进程和访问Manager.dict的开销,这最终会比常规的单线程/进程方法慢。您应该只使用Pool

from functools import partial
from multiprocessing import Manager, Pool

def select_star(table, counts, type_):  # counts and type_ will always be the counts dict and "prod", respectively
   pass

def main():
    mgr = Manager()
    counts = mgr.dict()

    p = Pool()
    func = partial(select_star, counts, "prod")  # Using a partial lets us pass extra parameters to select_start
    p.map(func, get_table_list())  # No need to use a manager for the list, since you're not passing the whole thing to the children.

if __name__ == "__main__":
    main()

答案 1 :(得分:1)

来自docs

  

在多处理中,通过创建Process对象生成进程   然后调用它的start()方法。

简而言之,它不管理开放进程的数量。它只是在调用start()时生成一个进程。