亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Python解決多線程運(yùn)行異步代碼報(bào)錯(cuò)"There?is?no?current?event?loop"

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

1. 引言

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

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

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

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

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

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

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

2. 問題背景

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

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

from concurrent.futures import ThreadPoolExecutor
import asyncio

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

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

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

2.2 原因分析

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

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

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

3. 解決方案

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

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

import requests

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

優(yōu)點(diǎn):

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

缺點(diǎn):

性能較低(每個(gè)請(qǐng)求阻塞線程)

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

如果必須用異步IO(如aiohttp),需為每個(gè)線程創(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):
    """在子線程中運(yùn)行異步函數(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)點(diǎn):

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

缺點(diǎn):

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

3.3 方案3:改用多進(jìn)程

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

from concurrent.futures import ProcessPoolExecutor

def check_phones_with_processes(phone_numbers):
    """使用進(jìn)程池規(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)點(diǎn):

  • 繞過GIL限制
  • 每個(gè)進(jìn)程有獨(dú)立的事件循環(huán)

缺點(diǎn):

  • 進(jìn)程啟動(dòng)開銷大
  • 進(jìn)程間通信復(fù)雜

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

在Java中,可以使用CompletableFuture和HttpClient實(shí)現(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)鍵點(diǎn):

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

5. 總結(jié)

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

最終建議:

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

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

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

相關(guān)文章

  • 使用Python處理PDF文件的實(shí)踐分享

    使用Python處理PDF文件的實(shí)踐分享

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

    django的ORM操作 增加和查詢

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

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

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

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

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

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

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

    python 音頻和視頻合并自動(dòng)裁剪

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

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

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

    python中使用序列的方法

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

    python字符串中的單雙引

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

    Python?OpenCV實(shí)現(xiàn)圖像增強(qiáng)操作詳解

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

最新評(píng)論