You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python Asyncio代码Mac3.7正常,Windows3.8无法触发指定打印语句的排查

问题分析与修复方案

首先,我一眼就注意到这个问题大概率是Python 3.8+ Windows平台下asyncio事件循环的默认切换导致的,结合你的代码细节,具体原因和修复方法如下:

核心原因

  1. 事件循环兼容性问题:Python 3.8起,Windows系统的asyncio默认事件循环从SelectorEventLoop换成了ProactorEventLoop,而aiohttp的TCPConnector在Proactor模式下存在调度兼容性问题,导致你的网络请求任务根本没被执行,自然不会走到fetch函数里的打印语句。
  2. 异常被静默吞掉:你用了asyncio.gather(*tasks, return_exceptions=True),这个参数会把任务中的所有异常当作返回值处理,而不是抛出,导致你看不到请求失败的具体原因(比如证书加载失败、路径错误等)。
  3. 冗余的事件循环代码:loop.create_future()那一行完全多余,虽然不影响功能,但容易混淆逻辑。

Windows环境下的修复方案

1. 强制指定兼容的事件循环

在创建事件循环时,针对Windows平台强制使用SelectorEventLoop,避免Proactor模式的坑:

import sys
import asyncio
from asyncio import SelectorEventLoop

def Initiate(list, folder_week, xmlfile, csvfile):
    bap = BAPRequest(folder_week, xmlfile, csvfile)
    # 区分平台设置事件循环
    if sys.platform.startswith('win32'):
        loop = SelectorEventLoop()
        asyncio.set_event_loop(loop)
    else:
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)
    # 移除多余的create_future,直接创建任务
    future = asyncio.ensure_future(bap.run(list, True))
    loop.run_until_complete(future)
    loop.close()

2. 调试并处理异常

先临时关闭return_exceptions=True,让异常直接抛出,方便你定位问题(比如证书路径是否正确):

# 调试阶段用这个,能直接看到错误
await asyncio.gather(*tasks)

调试完成后,建议加回异常处理,而不是单纯静默吞掉:

results = await asyncio.gather(*tasks, return_exceptions=True)
# 遍历结果,打印异常信息
for item_idx, result in enumerate(results):
    if isinstance(result, Exception):
        print(f"请求ID {r[item_idx]} 失败: {str(result)}")

3. 修复Windows路径问题

Windows下的路径分隔符是\,直接用./cert/...可能会出问题,改成跨平台的路径写法:

import os
# 获取当前脚本所在目录,拼接证书路径
cert_dir = os.path.join(os.path.dirname(__file__), 'cert')
cert_path = os.path.join(cert_dir, 'certificate.pem')
key_path = os.path.join(cert_dir, 'plainkey.pem')
sslcontext.load_cert_chain(cert_path, key_path)

4. 优化ClientSession配置

去掉force_close=True(async with会自动关闭Session),同时确保你的aiohttp是最新版本(避免旧版本的兼容性bug):

async with ClientSession(connector=aiohttp.TCPConnector(ssl=sslcontext)) as session:
    tasks = []
    sem = asyncio.Semaphore(1000)
    for i in r:
        task = asyncio.ensure_future(self.bound_fetch(sem, url + str(i), i, session, csv))
        tasks.append(task)
    await asyncio.gather(*tasks, return_exceptions=True)
    # 不需要手动调用session.close(),async with会自动处理

按照上面的步骤修改后,你的代码应该能在Windows 10 Python 3.8环境下正常执行到fetch函数里的打印语句了。

内容的提问来源于stack exchange,提问作者neelmeg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 15:27:39