пример - python subprocess pool




Как передать экземпляр multiprocessing.Pool в функцию обратного вызова apply_async? (2)

Вот моя основная программа факторизации, я добавил функцию обратного вызова в pool.apply_async(findK, args=(N,begin,end)) , сообщение о том, что prime factorization is over когда факторизация закончена, работает нормально.

import math
import multiprocessing 

def findK(N,begin,end):
    for k in range(begin,end):
        if N% k == 0:
            print(N,"=" ,k ,"*", N/k)
            return True
    return False


def prompt(result):
    if result:
        print("prime factorization is over")


def mainFun(N,process_num):
    pool = multiprocessing.Pool(process_num)
    for i in range(process_num):
        if i ==0 :
            begin =2
        else:
            begin = int(math.sqrt(N)/process_num*i)+1
        end = int(math.sqrt(N)/process_num*(i+1))
        pool.apply_async(findK, args=(N,begin,end) , callback = prompt)    
    pool.close()
    pool.join()    

if __name__ == "__main__":
    N = 684568031001583853
    process_num = 16
    mainFun(N,process_num)

Теперь я хочу изменить функцию обратного вызова в apply_async, чтобы изменить подсказку на функцию выключения, чтобы убить все другие процессы.

def prompt(result):
    if result:
        pool.terminate()

Экземпляр пула не определен в области приглашения или не передан в приглашение.
pool.terminate() не может работать в функции подсказки.
Как передать экземпляр multiprocessing.Pool в функцию apply_async'callback?
(Я сделал это в формате класса, просто чтобы добавить метод класса и вызвать self.pool.terminate может убить все другие процессы, как выполнить работу в формате функции?)

если не установить пул как глобальную переменную, можно ли передать пул в функцию обратного вызова?


Вы должны иметь pool конечном итоге в среде prompt . Одна из возможностей - переместить pool в глобальную область (хотя это не совсем лучшая практика). Это похоже на работу:

import math
import multiprocessing 

pool = None

def findK(N,begin,end):
    for k in range(begin,end):
        if N% k == 0:
            print(N,"=" ,k ,"*", N/k)
            return True
    return False


def prompt(result):
    if result:
        print("prime factorization is over")
        pool.terminate()


def mainFun(N,process_num):
    global pool
    pool = multiprocessing.Pool(process_num)
    for i in range(process_num):
        if i ==0 :
            begin =2
        else:
            begin = int(math.sqrt(N)/process_num*i)+1
        end = int(math.sqrt(N)/process_num*(i+1))
        pool.apply_async(findK, args=(N,begin,end) , callback = prompt)    
    pool.close()
    pool.join()    

if __name__ == "__main__":
    N = 684568031001583853
    process_num = 16
    mainFun(N,process_num)

Вы можете просто определить локальную функцию close как обратный вызов:

import math
import multiprocessing 


def findK(N, begin, end):
    for k in range(begin, end):
        if N % k == 0:
            print(N, "=", k, "*", N / k)
            return True
    return False


def mainFun(N, process_num):
    pool = multiprocessing.Pool(process_num)

    def close(result):
        if result:
            print("prime factorization is over")
            pool.terminate()
    for i in range(process_num):
        if i == 0:
            begin = 2
        else:
            begin = int(math.sqrt(N) / process_num * i) + 1
        end = int(math.sqrt(N) / process_num * (i + 1))
        pool.apply_async(findK, args=(N, begin, end), callback=close)
    pool.close()
    pool.join()


if __name__ == "__main__":
    N = 684568031001583853
    process_num = 16
    mainFun(N, process_num)

Вы также можете использовать partial функцию из functool , с

import functools

def close_pool(pool, results):
    if result:
        pool.terminate()

def mainFun(N, process_num):
    pool = multiprocessing.Pool(process_num)

    close = funtools.partial(close_pool, pool)
....




multiprocessing