父进程如何捕获子进程的异常?

线程是一个轻型实体,只有由很少的支持其独立运行的资源。 对于Python,线程拥有自己独立的栈, 当线程运行出错,线程会直接结束运行,当需要进行错误处理时,一般都会在线程中进行处理,但是如果只能由主进程来处理异常,那么线程要怎么才能将异常通知给主进程呢?对于进程,子进程的产生的异常如何让父进程去处理?
Multiprocessing PackageMultiprocessing是Python的一个多进程库,其实现的API类似threading. 其子模块dummy实现了与Multiprocessing.process相同的API,唯一的区别在于,dummy其实只是对threading做了一层封装而已. 这给不知道是CPU密集型或者是IO密集型的项目提供了便利,你可以自由地在多进程与多线程之间进行切换而只需更改一行代码。

调用error_callback函数在python3中, Multiprocessing对与apply_async()进行了改进,增加了一个默认参数error_callback=None,在这里你可以指定相应的错误处理函数,它将在子进程或者子线程运行出现异常是被调用. 与之对应的是callback=None参数(Python2也支持),它将在子进程或者子线程顺利运行之后被调用.
其原理,在于子线程或者子进程的一个_success属性, 其指出了运行状态.
   

[Python] 纯文本查看 复制代码

?

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

def get(self, timeout=None):        self.wait(timeout)

        if not self.ready():

            raise TimeoutError

        if self._success:

            return self._value

        else:

            raise self._value

 

    def _set(self, i, obj):

        self._success, self._value = obj

        if self._callback and self._success:

            self._callback(self._value)

        if self._error_callback and not self._success:

            self._error_callback(self._value)

        self._event.set()

        del self._cache[self._job]



需要注意的是,raise self._value语句抛出的是一个Exception.AttributeError,  可以看出只会抛出两种错误,一种是超时错误,一种是AttributeError. 而我们能利用的就是AttributeError, 在线程或者进程执行过程种出现错误, 我们只需要将合适的错误信息使用格式化字符串通过AttributeError传递出去,在error_callback去获取这个错误信息,在进行进一步的处理即可, 如果你只需要告知主进程出错了,那么只需要raise AttributeError即可.


检查线程退出状态由于线程出现异常退出和正常退出时的exitcode时不一样的,而线程结束运行后,内存又不会立即被回收,基于此,我们可以通过检查exitcode的方式来捕获线程中出现的错误,这种方法来自PengMeng's Blog, 一般地,Python中进程的属性, 或许可以达到和exitcode相同的效果. 这里不再深入讨论.

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Linux中,子进程异常中断时会向进程发送一个信号。进程可以通过捕获这个信号来获取子进程异常中断的代码。 常见的子进程异常中断信号是SIGCHLD。进程可以使用signal()或者sigaction()函数来捕获这个信号,并且在信号处理函数中调用waitpid()函数来获取子进程的退出状态。 下面是一个简单的示例代码: ```c #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <signal.h> #include <sys/wait.h> void sigchld_handler(int signum) { int status; pid_t pid = waitpid(-1, &status, WNOHANG); if (pid > 0) { if (WIFEXITED(status)) { printf("child process %d exited with code %d\n", pid, WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { printf("child process %d terminated abnormally with signal %d\n", pid, WTERMSIG(status)); } } } int main() { pid_t pid = fork(); if (pid == 0) { // 子进程 exit(123); } else if (pid > 0) { // 进程 signal(SIGCHLD, sigchld_handler); while (1) { sleep(1); } } else { // fork失败 perror("fork"); exit(1); } return 0; } ``` 在上面的示例代码中,进程在启动时注册了一个SIGCHLD信号处理函数sigchld_handler(),并且在其中调用waitpid()函数获取子进程的退出状态。在子进程中,我们简单地调用exit()函数退出,并且返回错误码123。当子进程退出时,进程会收到SIGCHLD信号,并且调用sigchld_handler()函数获取子进程的退出状态,并且输出到控制台上。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值