暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

python如何实现任务超时结束?

漫谈大数据与数据分析 2020-05-16
623

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

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

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

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

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

但图像识别接口,数据获取的过程就非常复杂,公众号请求服务器时只会给你一个媒体id。想通过媒体id下载图片,要先获取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(3False)  # 设定超时时间为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框架对接公众号了。


文章转载自漫谈大数据与数据分析,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论