如何将异常从一个进程传递到另一个进程?
How to pass exception from one process to another?
如果停止函数中的 运行 状态为 'stopped',我想在上传函数中引发异常。这似乎不起作用。我正在使用 Pipe 传递异常。怎么了?
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()
下面是一个示例,说明如何将异常对象从一个进程发送到另一个进程。我还尝试发送完整的异常信息(由 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
您可能想研究使用事件对象而不是管道和异常组合。通过使用事件原语在您的进程之间共享数据,您可以让上传函数监视事件并在停止函数发现问题时触发您的逻辑。
根据您的示例,我假设 instances 中的每个实例对象都是一个数组,因此通过使用附加元素扩展该数组,您可以为每个实例创建一个唯一的事件。
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
如果停止函数中的 运行 状态为 'stopped',我想在上传函数中引发异常。这似乎不起作用。我正在使用 Pipe 传递异常。怎么了?
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()
下面是一个示例,说明如何将异常对象从一个进程发送到另一个进程。我还尝试发送完整的异常信息(由 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
您可能想研究使用事件对象而不是管道和异常组合。通过使用事件原语在您的进程之间共享数据,您可以让上传函数监视事件并在停止函数发现问题时触发您的逻辑。
根据您的示例,我假设 instances 中的每个实例对象都是一个数组,因此通过使用附加元素扩展该数组,您可以为每个实例创建一个唯一的事件。
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