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

FastAPI中Python Swift客户端异步上传OpenStack对象存储的问题求解

解决方案:异步上传至OpenStack Swift

问题根源

你的代码里swift_connection.put_object()是同步阻塞方法,在异步函数中调用时会卡住整个asyncio事件循环,导致asyncio.gather()无法真正并行执行任务,反而因为异步调度的额外开销比纯同步代码更慢。从日志也能看出来,上传任务是顺序执行的,没有并行。

可行方案

1. 用线程池包装同步上传操作

把阻塞的put_object()放到线程池中执行,避免阻塞事件循环,让多个上传任务可以并行处理。Python 3.9+可以用asyncio.to_thread(),更低版本用loop.run_in_executor()。

修改后的代码示例:

import asyncio
import time
from io import BytesIO
from PIL import Image
from fastapi import FastAPI

# 省略认证代码
# [...]

app = FastAPI()

async def async_upload_image(idx, img):
    print("Start upload image:{}".format(idx))

    # 图片转字节(若这步耗时,同样可放到线程池)
    data = BytesIO()
    img.save(data, format='png')
    data = data.getvalue()

    # 将同步上传操作委托给线程池
    await asyncio.to_thread(
        swift_connection.put_object,
        'dev', 
        img['path'],  # 原代码写的是image['path'],这里修正为img
        data
    )

    print("Finish upload image:{}".format(idx))
    return True

@app.get("/test-async")
async def test_async():
    image = Image.open('./sketch-mountains-input.jpg')
    images = [image, image, image, image ]

    start = time.time()
    futures = [async_upload_image(idx, img) for idx, img in enumerate(images)]
    await asyncio.gather(*futures)
    end = time.time()
    print('It took {} seconds to finish execution'.format(round(end-start)))

    return True

修改后,多个上传任务会在不同线程并行执行,事件循环不会被阻塞,速度会远快于原来的伪异步实现,甚至超过纯同步执行效率。

2. 使用原生异步的OpenStack客户端

如果项目允许更换依赖,可选择支持异步的OpenStack Swift客户端库,比如openstacksdk的异步分支或专门的异步Swift客户端。这类库的put_object是原生异步方法,无需额外包装就能在asyncio环境下高效并行执行。

3. 批量上传优化(可选)

若上传文件数量较多,可考虑使用Swift的批量上传API(如bulk_upload),合并多个上传请求,减少HTTP连接开销,进一步提升整体效率。


内容的提问来源于stack exchange,提问作者Alexis.Rolland

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 19:05:44