繁体   English   中英

从多处理中的异常返回值

[英]return values from exceptions in multiprocessing

我正在调用一个函数task(url, param1, param2) ,该函数将API调用的结果返回到url = urlurl名称(如果API调用不起作用)。 我的task看起来像:

def task(url, param1, param2):
    try:
        make_api_call(url, param1, param2)
    except ValueError as e:
        print("val error")            
        return url

现在,我想将task应用于100个网址的列表,并开始对它们进行multiprocessing

import multiprocessing as mp

def run_tasks(urls, param1, param2):
    jobs = []
    for i in range(len(urls)):
        process = mp.Process(target=task, args=(urls[i], param1, param2))
        jobs.append(process)

    ## catch error processes
    error_urls = []

    ## start processes
    for j in jobs:
        j.start()

    ## finish processes
    for j in jobs:
        j.join()

从上面的run_tasks ,如何返回给我ValueErrorurl列表? 我尝试了error_urls.append(j.join()) ,但这没有用。

有两种方法可以从过程中获取结果。

方法1.使用Manager list 您无需使用锁在进程之间进行同步。

from multiprocessing import Process, Manager

def task(url, param1, param2, error_list):
    try:
        make_api_call(url, param1, param2)
    except ValueError as e:
        print("val error")            
        error_list.append(url)

def run_tasks(urls, param1, param2):

    error_list = Manager().list()    
    jobs = []

    for i in range(len(urls)):
        process = Process(target=task, args=(urls[i], param1, param2, error_list))
        jobs.append(process)

    ## start processes
    for j in jobs:
        j.start()

    ## finish processes
    for j in jobs:
        j.join()

方法2。使用concurrent.futures ProcessPoolExecutor 此方法易于理解,并且代码更少。

from concurrent import futures

def task(url, param1, param2):
    try:
        make_api_call(url, param1, param2)
    except ValueError as e:
        print("val error")            
        return url

def runt_tasks(urls, param1, param2):

    with futures.ProcessPoolExecutor() as executor:
        result = executor.map(task, urls, [param1] * len(urls), [param2] * len(urls))

    error_list = [item for item in result if item is not None]

最后,从问题描述开始。 这是一个IO敏感问题。 我建议您使用ThreadPoolExecutor 当您执行IO操作时,线程将释放GIL以让其他线程运行。 对于CPU敏感的问题,最好使用ProcessPoolExecutor asyncio是在Python 3中进行并发编程的另一种选择。

尝试共享内存。 使用此multiprocessing.sharedctypes.Array(typecode_or_type, size_or_initializer, *args[, lock])

您可以在run_tasks中定义它

from multiprocessing import Process, Lock
from multiprocessing.sharedctypes import Array
lock = Lock()
error_urls = Array(c_char_p, [], lock = lock)

def task(url, param1, param2):
    try:
       make_api_call(url, param1, param2)
    except ValueError as e:
       print("val error")            
       error_urls.append(url)

作为Array()的文档:

与RawArray()相同, 不同之处在于, 取决于锁的值,可以返回进程安全的同步包装而不是原始ctypes数组。

因此它是过程安全的。 更多关于阵列()是指这个 ,关于ctypes的(c_char_p)是指

暂无
暂无

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

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