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

如何使用Python OpenStack SDK实现文件上传进度条展示功能

解决方案

你可以通过包装原生文件对象的方式自定义读取回调逻辑,完全满足上传进度统计的需求,无需修改Python内置文件对象或OpenStack SDK的源码。


核心实现思路

OpenStack SDK上传文件时会调用传入文件对象的read()方法按块读取内容,我们只需要代理原生文件对象,重写read()方法,在每次读取操作完成后统计已读字节数、触发进度更新回调即可。

步骤1:实现可统计读取进度的文件包装类

import os

class ProgressFileWrapper:
    def __init__(self, file_path, read_callback):
        self.file = open(file_path, 'rb')
        self.total_size = os.path.getsize(file_path)
        self.read_bytes = 0
        self.read_callback = read_callback
        # 首次回调初始化进度
        self.read_callback(self.read_bytes, self.total_size)

    def read(self, size=-1):
        data = self.file.read(size)
        self.read_bytes += len(data)
        self.read_callback(self.read_bytes, self.total_size)
        return data
    
    # 实现上下文管理器支持with语句
    def __enter__(self):
        return self
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        self.file.close()
        return False

    # 代理其他原生文件对象的方法,避免SDK调用其他方法报错
    def __getattr__(self, attr):
        return getattr(self.file, attr)

步骤2:结合已有的进度条代码使用

以下是完整的使用示例:

# 原有进度条、颜色代码可直接复用
ESCAPE = {
    'c': { # colours
        'fg': { # foreground
            'b': '30', # black
            'r': '31', # red
            'g': '32', # green
            'y': '33', # yellow
            'u': '34', # blue
            'p': '35', # purple
            'c': '36', # cyan
            'w': '37', # white
        },
        'bg': { # background
            'b': '40', # black
            'r': '41', # red
            'g': '42', # green
            'y': '43', # yellow
            'u': '44', # blue
            'p': '45', # purple
            'c': '46', # cyan
            'w': '47', # white
        }
    },
    's': { # style
        'n': '0',  # none
        'b': '1',  # bold
        'u': '2',  # underline
        'n1': '3', # negative1
        'n2': '5', # negative2
    },
    't': '\033[{s};{fg};{bg}m' # template 
}

def colour(fg='w', bg='b', s='n'):
    return ESCAPE['t'].format(
            s=ESCAPE['s'][s],
            fg=ESCAPE['c']['fg'][fg],
            bg=ESCAPE['c']['bg'][bg]
    )

def get_progress_bar(percent, max_col=78):
    filled_len = int(max_col * percent / 100)
    bar = ' ' * filled_len
    togo = ' ' * (max_col - filled_len)
    return f"[{colour(bg='g')}{bar}{colour(bg='r')}{togo}{colour()}|{percent:6.2f}%]"

# 上传调用示例
if __name__ == "__main__":
    # 要上传的镜像路径
    image_path = "/path/to/your/image.iso"
    
    def update_progress(read_bytes, total_size):
        percent = (read_bytes / total_size) * 100
        # 清除当前行输出新进度
        print('\r' + get_progress_bar(percent), end='', flush=True)
        # 读完后换行
        if read_bytes >= total_size:
            print()
    
    # 用包装类代替原生open返回的文件对象
    with ProgressFileWrapper(image_path, update_progress) as f:
        # 这里直接把f传给OpenStack SDK的上传方法即可,比如:
        # conn.image.create_image(name="test-image", data=f, disk_format="iso")
        # 模拟读取操作,SDK内部会自动调用read触发进度更新
        while f.read(1024*1024):
            pass

注意事项

  • 如果上传时SDK会对文件内容做哈希校验等额外读取操作,你可以在包装类中加开关控制是否统计本次读取的字节数,避免进度重复计算
  • 对于超大文件,你可以降低进度条的刷新频率,比如每读取1MB才更新一次UI,避免频繁打印导致性能下降

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 08:15:01