如何将异常从一个进程传递到另一个进程?

时间:2016-12-08 18:26:15

标签: python python-multiprocessing

如果stop函数中的运行状态为“stopped”,我想在upload函数中引发异常。这似乎不起作用。我正在使用Pipe来传递异常。有什么问题?

Observation.related

2 个答案:

答案 0 :(得分:2)

以下是如何将Exception对象从一个进程发送到另一个进程的示例。我也尝试发送完整的异常信息(由sys.exc_info返回),但是,合理地说,这失败了。可以始终将回溯信息格式化为字符串并将其发送(请参阅回溯模块)。

在Ubuntu 14.04 Python 2.7,3.4(Ubuntu提供)和3.5(Continuum)上测试过。

from __future__ import print_function

import sys
import multiprocessing
import time

def upload(u1):
    i=0
    try:
        while True:
            print('>upload>',i)
            i+=1
            if u1.poll():
                # tvt = u1.recv()
                # raise tvt[0], tvt[1], tvt[2] # Python 2.7
                e = u1.recv()
                raise e
            time.sleep(0.1)
    except Exception as e:
        print('Exception caught:',e)
        print('exiting')

def stop(s1):
    try:
        while True:
            for j in range(100,110):
                time.sleep(0.1)
                if 105==j:
                    raise RuntimeError("oh dear at j={}".format(j))
    except Exception as e:
        # tvt = sys.exc_info()
        # s1.send(tvt) # doesn't work; tracebacks are not pickle'able
        s1.send(e)

if __name__ == '__main__':
    s1, u1 = multiprocessing.Pipe()
    s = multiprocessing.Process(target = stop, args = (s1,))
    u = multiprocessing.Process(target = upload, args = (u1,))
    s.start()
    u.start()
    u.join()

输出:

>upload> 0
>upload> 1
>upload> 2
>upload> 3
>upload> 4
>upload> 5
>upload> 6
Exception caught: oh dear at j=105
exiting

答案 1 :(得分:0)

您可能希望研究使用Event对象而不是Pipe和Exception组合。通过使用Event原语在您的进程之间共享数据,您可以使用Upload函数监视事件并在stop函数发现问题时触发逻辑。

根据您的示例,我假设实例中的每个实例对象都是一个数组,因此通过使用其他元素扩展该数组,您可以为每个实例分配一个唯一的事件。

def upload(instances, u1):
for instance in instance:
    if instance[5].is_set(): # events only return TRUE if they are set
        #Exception logic would go here

    else: 
        u1.recv()
        #do_something


def stop(instances, s1):
for instance in instances:
    RunningStatus = instance[4]
    if RunningStatus.lower() == 'stopped'.lower():
        instance[5].set() # Set the event to TRUE 

if __name__ == '__main__':
    for instance in instances:
        instance[5] = multiprocessing.Event() # create a new event semaphore 
    s = multiprocessing.Process(target = stop, args = (instances, s1,))
    u = multiprocessing.Process(target = upload, args = (instances, u1))
    s.start()
    u.start()
    u.join()

可以在此处找到多处理原语的完整列表:https://docs.python.org/2/library/multiprocessing.html#synchronization-primitives

以下是其他多处理对象的基元的各种用途的一些很好的例子:https://pymotw.com/2/multiprocessing/communication.html