欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Python解決多線程運行異步代碼報錯"There?is?no?current?event?loop"

 更新時間:2025年04月16日 09:56:17   作者:碼農(nóng)阿豪@新空間  
在Python開發(fā)中,我們經(jīng)常需要同時處理高并發(fā)網(wǎng)絡(luò)請求和CPU密集型任務(wù),不過當(dāng)嘗試在多線程環(huán)境中運行異步代碼時,可能會報錯"There?is?no?current?event?loop",下面我們看看具體的解決方法吧

1. 引言

在Python開發(fā)中,我們經(jīng)常需要同時處理高并發(fā)網(wǎng)絡(luò)請求和CPU密集型任務(wù)。這時,開發(fā)者可能會選擇:

  • 多線程(ThreadPoolExecutor)處理阻塞IO任務(wù)
  • 異步IO(asyncio + aiohttp)優(yōu)化高并發(fā)網(wǎng)絡(luò)請求

然而,當(dāng)嘗試在多線程環(huán)境中運行異步代碼時,可能會遇到錯誤:

ERROR - There is no current event loop in thread 'Thread-4'.

本文將分析該問題的原因,并提供3種解決方案,包括:

  • 純同步方案(requests)
  • 異步+多線程方案(aiohttp + asyncio.run_coroutine_threadsafe)
  • 多進程替代方案(ProcessPoolExecutor)

最后,我們還會給出Java的等效實現(xiàn)(基于CompletableFuture和HttpClient)。

2. 問題背景

2.1 錯誤復(fù)現(xiàn)

以下代碼在多線程中調(diào)用異步函數(shù)時崩潰:

from concurrent.futures import ThreadPoolExecutor
import asyncio

async def async_task():
    await asyncio.sleep(1)
    return "Done"

def run_in_thread():
    # 直接調(diào)用會報錯:There is no current event loop in thread
    result = async_task()  # ? 錯誤!
    return result

with ThreadPoolExecutor() as executor:
    future = executor.submit(run_in_thread)
    print(future.result())

2.2 原因分析

asyncio 的事件循環(huán)是線程局部的,每個線程需要自己的事件循環(huán)。

主線程默認有事件循環(huán),但子線程沒有。

直接在新線程中調(diào)用 await 會導(dǎo)致 RuntimeError。

3. 解決方案

3.1 方案1:純同步實現(xiàn)(推薦)

如果不需要高性能異步IO,直接改用同步請求庫(如requests):

import requests

def sf_express_order_count_sync(consigneePhone, cookie, createTimeStart, createTimeEnd):
    """同步版:使用requests發(fā)送HTTP請求"""
    url = 'https://sd.sf-express.com/api/merge/order/count'
    response = requests.post(url, headers=headers, json=payload)
    return response.json()

優(yōu)點:

  • 代碼簡單,無需處理事件循環(huán)
  • 兼容所有Python版本

缺點:

性能較低(每個請求阻塞線程)

3.2 方案2:異步+多線程混合

如果必須用異步IO(如aiohttp),需為每個線程創(chuàng)建事件循環(huán):

import aiohttp

async def sf_express_order_count_async(consigneePhone, cookie, createTimeStart, createTimeEnd):
    """異步版:使用aiohttp"""
    async with aiohttp.ClientSession() as session:
        async with session.post(url, headers=headers, json=payload) as resp:
            return await resp.json()

def run_async_in_thread(async_func, *args):
    """在子線程中運行異步函數(shù)"""
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
    try:
        return loop.run_until_complete(async_func(*args))
    finally:
        loop.close()

???????# 在線程池中調(diào)用
with ThreadPoolExecutor() as executor:
    future = executor.submit(
        run_async_in_thread, 
        sf_express_order_count_async, 
        "13112345678", 
        "cookie123", 
        1630000000
    )
    print(future.result())

優(yōu)點:

  • 高性能(異步IO + 多線程)
  • 適用于高并發(fā)場景

缺點:

  • 代碼復(fù)雜度高
  • 需要手動管理事件循環(huán)

3.3 方案3:改用多進程

如果異步+多線程仍不滿足需求,可用ProcessPoolExecutor替代:

from concurrent.futures import ProcessPoolExecutor

def check_phones_with_processes(phone_numbers):
    """使用進程池規(guī)避GIL和事件循環(huán)問題"""
    with ProcessPoolExecutor() as executor:
        futures = [executor.submit(has_orders, phone) for phone in phone_numbers]
        for future in as_completed(futures):
            if future.result():
                return future.result()

優(yōu)點:

  • 繞過GIL限制
  • 每個進程有獨立的事件循環(huán)

缺點:

  • 進程啟動開銷大
  • 進程間通信復(fù)雜

4. Java等效實現(xiàn)

在Java中,可以使用CompletableFuture和HttpClient實現(xiàn)類似功能:

import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.concurrent.CompletableFuture;

public class SfExpressChecker {
    private static final HttpClient httpClient = HttpClient.newHttpClient();

    public static CompletableFuture<Boolean> hasOrdersAsync(String phone, String cookie) {
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create("https://sd.sf-express.com/api/merge/order/count"))
                .header("Content-Type", "application/json")
                .header("token", cookie)
                .POST(HttpRequest.BodyPublishers.ofString(
                    String.format("{\"consigneePhone\":\"%s\"}", phone)))
                .build();

        return httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString())
                .thenApply(response -> {
                    JsonObject json = JsonParser.parseString(response.body()).getAsJsonObject();
                    return json.get("result").getAsJsonObject().get("total").getAsInt() > 0;
                });
    }

    public static void main(String[] args) {
        CompletableFuture<Boolean> future = hasOrdersAsync("13112345678", "cookie123");
        future.thenAccept(hasOrders -> System.out.println("Has orders: " + hasOrders));
        future.join(); // 阻塞等待結(jié)果
    }
}

關(guān)鍵點:

  • Java的HttpClient原生支持異步
  • CompletableFuture簡化異步編程
  • 無需手動管理事件循環(huán)

5. 總結(jié)

方案適用場景優(yōu)點缺點
純同步(requests)低并發(fā)、簡單場景代碼簡單性能差
異步+多線程高并發(fā)網(wǎng)絡(luò)請求高性能需管理事件循環(huán)
多進程CPU密集型+高IO混合任務(wù)繞過GIL進程開銷大

最終建議:

  • 優(yōu)先使用同步代碼(除非性能瓶頸明確)
  • 異步+多線程適合高并發(fā)HTTP請求
  • Java的異步方案更優(yōu)雅(推薦CompletableFuture

通過合理選擇方案,可以避免There is no current event loop錯誤,并構(gòu)建高性能的并發(fā)應(yīng)用。

到此這篇關(guān)于Python解決多線程運行異步代碼報錯"There is no current event loop"的文章就介紹到這了,更多相關(guān)Python解決多線程運行異步報錯內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 使用Python處理PDF文件的實踐分享

    使用Python處理PDF文件的實踐分享

    在現(xiàn)代數(shù)字化時代,PDF(Portable?Document?Format)文件已經(jīng)成為廣泛使用的電子文檔格式,這篇文章主要為分享了Python處理PDF文件的簡介與實踐,需要的可以參考下
    2023-06-06
  • django的ORM操作 增加和查詢

    django的ORM操作 增加和查詢

    這篇文章主要介紹了django的ORM操作 增加和查詢,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-07-07
  • Python中JSON的使用方法(超詳細)

    Python中JSON的使用方法(超詳細)

    JSON是一種輕量級的數(shù)據(jù)交換格式,它是JavaScript的子集,易于人閱讀和編寫,這篇文章主要介紹了Python中JSON的基本使用,需要的朋友可以參考下
    2022-11-11
  • Python實現(xiàn)國外賭場熱門游戲Craps(雙骰子)

    Python實現(xiàn)國外賭場熱門游戲Craps(雙骰子)

    這篇文章主要介紹了Python實現(xiàn)國外賭場熱門游戲Craps(雙骰子)的源碼及運行方法,十分簡單,有需要的小伙伴可以參考下。
    2015-03-03
  • Python機器學(xué)習(xí)庫scikit-learn安裝與基本使用教程

    Python機器學(xué)習(xí)庫scikit-learn安裝與基本使用教程

    這篇文章主要介紹了Python機器學(xué)習(xí)庫scikit-learn安裝與基本使用,較為詳細的介紹了機器學(xué)習(xí)庫scikit-learn的功能、原理、基本安裝與簡單使用方法,需要的朋友可以參考下
    2018-06-06
  • python 音頻和視頻合并自動裁剪

    python 音頻和視頻合并自動裁剪

    本文主要介紹了python 音頻和視頻合并自動裁剪,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-06-06
  • python實現(xiàn)圖片文件批量重命名

    python實現(xiàn)圖片文件批量重命名

    這篇文章主要為大家詳細介紹了python實現(xiàn)圖片文件批量重命名,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-05-05
  • python中使用序列的方法

    python中使用序列的方法

    這篇文章主要介紹了python中使用序列的方法,較為詳細的分析了Python序列的原理與使用技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-08-08
  • python字符串中的單雙引

    python字符串中的單雙引

    下面小編就為大家?guī)硪黄猵ython字符串中的單雙引。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-02-02
  • Python?OpenCV實現(xiàn)圖像增強操作詳解

    Python?OpenCV實現(xiàn)圖像增強操作詳解

    由于很多不確定因素,導(dǎo)致圖像采集的光環(huán)境極其復(fù)雜;為了提高目標檢測模型的泛化能力,本文將使用python中的opencv模塊實現(xiàn)常見的圖像增強方法,感興趣的可以了解一下
    2022-10-10

最新評論