分享

python如何实现任务超时处理?

 小小明代码实体 2021-11-30

在做公众号开发-被动回复消息的过程中,官方要求如下:

假如服务器无法保证在五秒内处理并回复,必须做出下述回复,这样微信服务器才不会对此作任何处理,并且不会发起重试(这种情况下,可以使用客服消息接口进行异步回复),否则,将出现严重的错误提示。详见下面说明:

1、直接回复success(推荐方式) 2、直接回复空串(指字节长度为0的空字符串,而不是XML结构体中content字段的内容为空)

一旦遇到以下情况,微信都会在公众号会话中,向用户下发系统提示“该公众号暂时无法提供服务,请稍后再试”:

1、开发者在5秒内未回复任何内容 2、开发者回复了异常数据,比如JSON数据等

但图像识别接口,数据获取的过程就非常复杂,首先要获取accessToken,然后通过媒体接口去下载用户发来的图片,然后再调用本地复杂的识别逻辑,图片一旦过大根本无法保证5秒内处理完毕,所以我想了个简单做法,如果处理时间超过3秒,就直接结束掉处理线程回复一个success。但是我有点犯难,python内置库压根没有直接可以用的类或方法啊。

回忆起java,要实现这样的效果多简单:

image-20200515230010323

用线程池创建Future直接就可以实现了,代码如下:

import java.io.IOException;
import java.util.Random;
import java.util.concurrent.*;

public class Test {
    public static void main(String[] args) throws IOException, ExecutionException, InterruptedException {
        final ExecutorService exec = Executors.newFixedThreadPool(1);
        final Random random = new Random();
        Callable<String> call = () -> {
            //开始执行耗时操作
            int millis = random.nextInt(7000);
            System.out.println("预计处理耗时" + millis + "毫秒");
            Thread.sleep(millis);
            return "顺利识别完图片,执行完毕";
        };

        while (true) {
            Future<String> future = exec.submit(call);
            try {
                String result = future.get(1000 * 3, TimeUnit.MILLISECONDS); //任务处理超时时间设为 3 秒
                System.out.println("三秒内已经"+result);
            } catch (TimeoutException ex) {
                System.out.println("已超时,请重试....");
//                ex.printStackTrace();
            } catch (Exception e) {
                System.out.println("处理失败.");
                e.printStackTrace();
            } finally {
                future.cancel(true);
            }
        }
        // 关闭线程池
//        exec.shutdown();
    }
}

结果如下:

预计处理耗时4102毫秒
已超时,请重试....
预计处理耗时2831毫秒
三秒内已经顺利识别完图片,执行完毕
预计处理耗时4106毫秒
已超时,请重试....
预计处理耗时5341毫秒
已超时,请重试....
预计处理耗时5705毫秒
已超时,请重试....
预计处理耗时535毫秒
三秒内已经顺利识别完图片,执行完毕
预计处理耗时1441毫秒
三秒内已经顺利识别完图片,执行完毕
预计处理耗时5463毫秒
已超时,请重试....
预计处理耗时5192毫秒
已超时,请重试....
预计处理耗时441毫秒
三秒内已经顺利识别完图片,执行完毕
预计处理耗时2147毫秒
三秒内已经顺利识别完图片,执行完毕
...

可是python如何实现这样的效果呢?我踩了无数的坑,试验了无数的方法,发现eventlet特别好使,写出来的代码比java更简单。

当然使用前,可能需要先安装:

pip install eventlet

然后编写的代码如下:

import random

import time
import eventlet  # 导入eventlet这个模块

eventlet.monkey_patch()  # 必须加这条代码

while 1:
    t = eventlet.Timeout(3, False)  # 设定超时时间为3秒
    try:
        randtime = random.random() * 7
        print(f"预计处理耗时:{randtime}秒")
        time.sleep(randtime)
        print('3秒内顺利识别完图片,执行完毕')
    except eventlet.timeout.Timeout as e:
        print('已超时,请重试...')
    finally:
        t.cancel()

结果:

预计处理耗时:4.658229865957732秒
已超时,请重试...
预计处理耗时:6.228621136519976秒
已超时,请重试...
预计处理耗时:5.377029668612019秒
已超时,请重试...
预计处理耗时:2.019114138389199秒
3秒内顺利识别完图片,执行完毕
预计处理耗时:6.853365361191674秒
已超时,请重试...
预计处理耗时:2.7689501896254516秒
3秒内顺利识别完图片,执行完毕
预计处理耗时:1.2264810150796943秒
3秒内顺利识别完图片,执行完毕
预计处理耗时:0.7978596675396795秒
3秒内顺利识别完图片,执行完毕
预计处理耗时:1.682507234965843秒
3秒内顺利识别完图片,执行完毕
预计处理耗时:6.754677994247869秒
已超时,请重试...
预计处理耗时:1.9340315674113921秒
3秒内顺利识别完图片,执行完毕
...

哈哈,顺利实现了这个效果,然后我就把类似的逻辑引入到web框架对接公众号了。

    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多