python如何實現任務超時處理?

在做公衆號開發-被動回覆消息的過程中,官方要求如下:

假如服務器無法保證在五秒內處理並回復,必須做出下述回覆,這樣微信服務器纔不會對此作任何處理,並且不會發起重試(這種情況下,可以使用客服消息接口進行異步回覆),否則,將出現嚴重的錯誤提示。詳見下面說明:

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框架對接公衆號了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章