简体   繁体   English

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

[英]How to pass exception from one process to another?

I want to raise an exception in the upload function if the running status in stop function is 'stopped'. 如果停止功能的运行状态为“停止”,我想在上传功能中引发异常。 This doesn't seem to work. 这似乎不起作用。 I am using Pipe to pass the exception. 我正在使用Pipe传递异常。 What is wrong? 怎么了?

def upload(instances, u1):
    for instance in instance:
        try:
            u1.recv()
            #do_something
        except:
            #do_something_else
            continue         

def stop(instances, s1):
    for instance in instances:
        RunningStatus = instance[4]
        if RunningStatus.lower() == 'stopped'.lower():
            s1.send(Exception) # I want to raise exception in upload function 
                               # from here

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

Here's an example of how you could send Exception objects from one process to another. 这是如何将Exception对象从一个进程发送到另一个进程的示例。 I also tried sending complete exception information (as returned by sys.exc_info), but, reasonably enough, this fails. 我还尝试发送完整的异常信息(由sys.exc_info返回),但是,这样做足够合理。 One could always format the traceback info to a string and send that instead (see the traceback module). 可以始终将回溯信息格式化为字符串并将其发送(参见回溯模块)。

Tested on Ubuntu 14.04 Python 2.7, 3.4 (Ubuntu-provided), and 3.5 (Continuum). 已在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()

Output: 输出:

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

You might want to look into using an Event object instead of a Pipe and Exception combination. 您可能想研究使用事件对象而不是管道和异常组合。 By using an Event primitive to share data between your processes you could have the Upload function watch the event and trigger your logic when the stop function finds an issue. 通过使用事件原语在您的进程之间共享数据,您可以让Upload函数监视事件并在stop函数发现问题时触发您的逻辑。

Based on your example I'm assuming that each instance object in instances is an array, so by extending that array with an additional element you can have a unique event for each instance. 根据您的示例,我假设实例中的每个实例对象都是一个数组,因此,通过使用附加元素扩展该数组,您可以为每个实例具有唯一事件。

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()

The full list of multiprocessing primitives can be found over here: https://docs.python.org/2/library/multiprocessing.html#synchronization-primitives 可以在以下位置找到多处理原语的完整列表: https : //docs.python.org/2/library/multiprocessing.html#synchronization-primitives

Here's some good examples of various uses for primitives other multiprocessing objects: https://pymotw.com/2/multiprocessing/communication.html 这是其他多处理对象对原语的各种用法的一些很好的示例: https : //pymotw.com/2/multiprocessing/communication.html

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

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