Python SDK V1到V2迁移指南

OSS Python SDK V2版是对V1版的全面重构,简化了身份验证、请求重试和错误处理等底层操作,提供更灵活的参数配置和新的高级接口(如分页器、文件上传/下载管理器)。本文介绍如何从Python SDK V1版本迁移到Python SDK V2 版本。

主要变更概览

迁移到V2版 SDK时,您需要了解以下主要变更:

  1. 客户端创建方式:V2版本把Client的创建函数从Bucket修改为Client

  2. API调用模式:从函数参数传递方式改为请求/响应模型

  3. 包名称变更:从oss2变更为alibabacloud_oss_v2

  4. 类和方法名称变化:部分API名称发生变化

  5. 类型注解:V2版本引入完整类型注解,提升代码可维护性

完整迁移步骤

第一步:环境准备

  1. 评估现有代码

    • 梳理现有代码中使用OSS SDK的位置

    • 记录您使用了哪些OSS功能和接口

    • 确定依赖关系,避免迁移过程中出现意外问题

  2. 更新Python运行环境:

    • V2版本要求Python的运行环境版本最低为3.8。请参考Python官网下载和安装Python 3.8及以上版本的运行环境,通过以下命令检查Python是否安装成功:

      python --version
  3. 保留V1SDK以便逐步迁移,安装V2SDK

    pip install alibabacloud-oss-python-sdk-v2
  4. 创建测试环境

    • 建议创建独立的测试环境,而不是直接在生产环境修改

    • 配置测试数据和测试用例,用于验证迁移后的代码

第二步:修改导入语句

功能变更

Python SDK V2版本启用了新的代码仓库(alibabacloud-oss-python-sdk-v2),并对代码结构进行了优化调整。此次调整按照功能模块对代码进行了重新组织,旨在提升代码的可读性和维护性。以下是各个模块的路径及其相应说明:

模块路径

说明

alibabacloud_oss_v2

SDK核心模块,包含基础接口和高级接口的功能实现

alibabacloud_oss_v2.credentials

负责管理访问OSS服务所需的凭证,确保安全、有效地进行身份验证

alibabacloud_oss_v2.retry

重试相关功能实现

alibabacloud_oss_v2.signer

签名相关功能实现

alibabacloud_oss_v2.transport

HTTP客户端相关功能实现

alibabacloud_oss_v2.crypto

客户端加密相关功能实现

代码示例

  1. 替换包导入: 将所有oss2的导入替换为对应的alibabacloud_oss_v2导入:

    # V1版
    import oss2
    from oss2 import Auth, Bucket, Service
    
    # V2版
    import alibabacloud_oss_v2
    from alibabacloud_oss_v2 import Client, Config
    
  2. 导入模型类

    # V2SDK需要导入请求和结果模型
    from alibabacloud_oss_v2.models import (
        PutObjectRequest, GetObjectRequest, DeleteObjectRequest, 
        ListObjectsRequest, PutBucketRequest, GetBucketAclRequest
        # 其他您需要的请求类...
    )
  3. 导入其他工具类

    # 根据需要导入V2SDK的工具类
    from alibabacloud_oss_v2 import (
        Uploader, Downloader, Copier, 
        ListObjectsPaginator, ListObjectsV2Paginator
    )

第三步:修改创建客户端代码

功能变更

  1. V2 版本把客户端Client的创建函数从Bucket包迁移至Client包中。

  2. V2版本对配置客户端进行了优化,所有配置项现已统一归类到config下,支持通过编程方式覆盖默认配置,从而提供更高的灵活性和便捷性。

  3. V2版本默认采用V4签名算法,因此在配置客户端时必须指定阿里云通用Region ID作为发起请求地域的标识。

  4. V2版本支持根据所选区域(Region)自动生成访问域名(Endpoint)。当您访问公网域名时,无需手动设置Endpoint,系统将自动依据您的区域信息进行构造。

代码示例

V1版示例

# -*- coding: utf-8 -*-
import oss2
from oss2.credentials import EnvironmentVariableCredentialsProvider

# 从环境变量中获取访问凭证。运行本代码示例之前,请先配置环境变量。
auth = oss2.ProviderAuthV4(EnvironmentVariableCredentialsProvider())
# 填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
endpoint = 'https://oss-cn-hangzhou.aliyuncs.com'
# 填写Endpoint对应的Region信息,例如cn-hangzhou。
region = 'cn-hangzhou'

# 填写Bucket名称。
bucket = oss2.Bucket(auth, endpoint, 'examplebucket', region=region) 

# 使用创建好的bucket执行后续操作...

V2版示例

  1. V2版中,使用新的配置加载方式,需先创建cfg并注入region等信息。

  2. 使用oss.Client(cfg)方法替代旧版的oss2.Bucket方法。

import alibabacloud_oss_v2 as oss

def main():
    # 从环境变量中加载凭证信息,用于身份验证
    credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()

    # 加载SDK的默认配置,并设置凭证提供者
    cfg = oss.config.load_default()
    cfg.credentials_provider = credentials_provider

    # 只填写Region即可
    # 填写Bucket所在地域。以华东1(杭州)为例,Region填写为cn-hangzhou
    cfg.region = 'cn-hangzhou'

    # 使用配置好的信息创建OSS客户端
    client = oss.Client(cfg)

    # 使用创建好的client执行后续操作...

关于V2版配置客户端的更多详细示例,请参见配置客户端

关于V2版配置访问凭证的更多详细示例,请参见配置访问凭证

第四步:修改基础API调用方式

功能变更

  1. SDK V2版本提供了与REST API对应的接口,把这类接口叫做基础接口或者低级别API。您可以通过这些接口访问OSS的服务,例如创建存储空间,上传文件和下载文件等。

  2. V2版本中,各个基础API接口遵循一套标准化的命名规则。每个操作方法均命名为<OperationName>形式,其中,操作的请求参数类被定义为<OperationName>Request,而操作的结果返回值则定义为<OperationName>Result,如下所示。

    def <OperationName>(self, request: models.<OperationRequestName>, **kwargs
                     ) -> models.<OperationResulttName>:            
        return operations.<OperationName>(self._client, request, **kwargs)

关于基础API的更多详细说明,请参考开发者指南-基础接口

代码示例

  1. 创建存储空间

    # V1版
    bucket.create_bucket()
    # 或者带权限
    bucket.create_bucket(oss2.BUCKET_ACL_PRIVATE)
    
    # V2版
    request = PutBucketRequest(bucket='your-bucket-name')
    client.put_bucket(request)
    # 或者带权限
    request = PutBucketRequest(
        bucket='your-bucket-name',
        acl=BucketAcl.PRIVATE
    )
    client.put_bucket(request)
  2. 获取存储空间ACL

    # V1版
    result = bucket.get_bucket_acl()
    acl = result.acl
    
    # V2版
    request = GetBucketAclRequest(bucket='your-bucket-name')
    result = client.get_bucket_acl(request)
    acl = result.acl
    
  3. 删除存储空间

    # V1版
    bucket.delete_bucket()
    
    # V2版
    request = DeleteBucketRequest(bucket='your-bucket-name')
    client.delete_bucket(request)
  4. 列举存储空间

    # V1版
    service = oss2.Service(auth, endpoint)
    result = service.list_buckets()for bucket_info in result.buckets:print(bucket_info.name)
    
    # V2版 - 基本用法
    request = ListBucketsRequest()
    result = client.list_buckets(request)
    for bucket_info in result.buckets:
        print(bucket_info.name)   
  5. 上传对象

    # V1版 - 上传内容
    result = bucket.put_object('object-key', 'content')
    
    # V2版 - 上传内容
    request = PutObjectRequest(
        bucket='your-bucket-name',
        key='object-key',
        content='content')
    result = client.put_object(request)
    
    # V1版 - 上传文件
    result = bucket.put_object_from_file('object-key', 'local-file.txt')
    
    # V2版 - 上传文件
    request = PutObjectRequest(
        bucket='your-bucket-name',
        key='object-key')
    result = client.put_object_from_file(request, 'local-file.txt')
  6. 下载对象

    # V1版 - 获取对象内容
    result = bucket.get_object('object-key')
    content = result.read()
    
    # V2版 - 获取对象内容
    request = GetObjectRequest(
        bucket='your-bucket-name',
        key='object-key')
    result = client.get_object(request)
    content = result.read()
    
    # V1版 - 下载到文件
    bucket.get_object_to_file('object-key', 'local-file.txt')
    
    # V2版 - 下载到文件
    request = GetObjectRequest(
        bucket='your-bucket-name',
        key='object-key')
    client.get_object_to_file(request, 'local-file.txt')
  7. 删除对象

    # v1版
    bucket.delete_object('object-key')
    
    # V2版
    request = DeleteObjectRequest(
        bucket='your-bucket-name',
        key='object-key')
    client.delete_object(request)
  8. 列举对象

    # V1版
    for obj in oss2.ObjectIterator(bucket, prefix='photos/'):
        print(obj.key)
        
    # V2版 - 基本用法
     client = oss.Client(cfg)
    
    paginator = client.list_objects_v2_paginator()
    for page in paginator.iter_page(oss.ListObjectsV2Request(
        bucket='your-bucket-name',
    ):
    for o in page.contents:
        print(f'Object: {o.key}, Size: {o.size}, Last_modified: {o.last_modified}')

关于V2版基础API的更多示例代码,请参见对象/文件

第五步:修改高级API调用方式(可选)

预签名接口

变更点

V2版本把预签名接口名称从sign_url修改为presign,同时把接口代码实现迁移到Client类中。接口形式如下:

def presign(self, request: PresignRequest, **kwargs) -> PresignResult:

对于request参数,其类型与基础API接口中的<OperationName>Request一致。

对于返回结果,除了返回预签名URL外,还返回 HTTP 方法,过期时间和被签名的请求头,如下:

class PresignResult:
    def __init__(
        self,
        method: Optional[str] = None,
        url: Optional[str] = None,
        expiration: Optional[datetime.datetime] = None,
        signed_headers: Optional[MutableMapping] = None,
    ) -> None:
        self.method = method
        self.url = url
        self.expiration = expiration
        self.signed_headers = signed_headers

关于V2版预签名接口的详细使用说明,请参考开发者指南-预签名接口

代码示例
  1. 使用预签名URL上传

    # V1版 
    url = bucket.sign_url('PUT', 'object-key', 3600) # 3600秒有效期
    
    # V2版
    client = oss.Client(cfg)
    pre_result = client.presign(oss.PutObjectRequest(
        bucket=args.bucket,
        key=args.key,
    ),expires=timedelta(seconds=3600)) # 3600秒有效期

    关于V2版使用预签名URL上传文件的完整示例代码,请参见使用预签名URL上传

  2. 使用预签名URL下载

    # V1版
    url = bucket.sign_url('GET', 'object-key', 3600)  # 3600秒有效期
    
    # V2版
    client = oss.Client(cfg)
    pre_result = client.presign(
        oss.GetObjectRequest(
            bucket=args.bucket, 
            key=args.key,    
    ),expires=timedelta(seconds=3600)) # 3600秒有效期

    关于V2版使用预签名URL下载文件的完整示例代码,请参见使用预签名URL下载

文件传输管理器

变更点

V2版本使用传输管理器'Uploader''Downloader' 'Copier'分别管理对象的上传,下载和拷贝。 同时移除了原有的断点续传接口Bucket.UploadFileBucket.DownloadFileBucket.CopyFile

接口对比如下:

使用场景

V2

V1

上传文件

Uploader.upload_file

bucket.put_object_from_file

上传流

Uploader.upload_from

不支持

下载到文件

Downloader.download_file

bucket.get_object_to_file

拷贝对象

Copier.copy

bucket.copy_object

关于V2版文件传输管理器的详细使用说明,请参考开发者指南-传输管理器

代码示例
  1. 文件上传管理器

    # V1版
    oss2.resumable_upload(bucket, 'object-key', 'local-file.zip', 
                         multipart_threshold=100*1024,
                         part_size=100*1024,
                         num_threads=4)
                         
    # V2版 - 使用文件上传管理器
    uploader = client.uploader()
    
    # 调用方法执行文件上传操作
    result = uploader.upload_file(
        oss.PutObjectRequest(
            bucket='your-bucket-name',  
            key='object-key',   
        ),
        filepath='local-file.zip',
        part_size=10  * 1024 * 1024,
        part_num=3
    )

    关于V2版文件上传管理器的更多详细说明,请参见开发者指南-文件上传管理器

    关于V2版文件上传管理器的完整示例代码,请参见文件上传管理器

  2. 文件下载管理器

    # V1版
    oss2.resumable_download(bucket, 'object-key', 'local-file.zip',
                           multiget_threshold=100*1024,
                           part_size=100*1024,
                           num_threads=4)
                           
    # V2版 - 使用文件下载管理器
    down_loader = client.downloader()
    
    result = down_loader.download_file(oss.GetObjectRequest(
        bucket='your-bucket-name',  
        key='object-key',
    ), filepath='local-file.zip')

    关于V2版文件下载管理器的更多详细说明,请参见开发者指南-文件下载管理器

    关于V2版文件下载管理器的完整示例代码,请参见文件下载管理器

  3. 文件拷贝管理器

    # V1版
    bucket.copy_object('src-bucket', 'src-object', 'dst-object')
    
    # V2版
    request = CopyObjectRequest(
        bucket='your-bucket-name',
        key='dst-object',
        source_bucket='src-bucket',
        source_key='src-object')
    client.copy_object(request)
    
    # V2版 - 使用文件拷贝管理器
    client = oss.Client(cfg)
    copier = client.copier()
    result = copier.copy(
        oss.CopyObjectRequest(
            bucket=args.bucket,
            key=args.key,
            source_bucket=args.source_bucket,
            source_key=args.source_key,
        )
    )

    关于V2版文件拷贝管理器的更多详细说明,请参见开发者指南-文件拷贝管理器

    关于V2版文件拷贝管理器的完整示例代码,请参见文件拷贝管理器

第六步:测试和验证

  1. 编写单元测试

    为确保迁移后功能的正确性,您需要为每个迁移的功能编写详细的单元测试案例。这些测试应涵盖所有关键操作,并验证其行为与旧版SDK保持一致。重点包括:

    • 基础功能测试:如创建资源、查询状态、更新数据和删除资源等。

    • 边界条件测试:测试极端情况下的应用行为,例如处理极大或极小的数据集、异常输入等。

    • 错误处理测试:确保在出现错误时(如网络超时、无效输入),应用能够正确处理并给出合适的反馈。

  2. 增量测试

    采用增量式的方法进行迁移和测试,可以有效降低风险:

    • 选择一个小模块开始:先从一个相对独立且不复杂的小模块开始迁移,并为其编写完整的测试案例。

    • 进行全面测试:在确认该模块迁移成功且所有测试通过后,再逐步迁移到其他部分。这种方法有助于及时发现并解决问题,避免大规模回滚。

  3. 兼容性测试

    确保新版本SDK与您的整个技术栈及其他依赖项兼容至关重要:

    • 内部系统兼容性:验证新版本是否与现有的内部系统和架构兼容。

    • 第三方服务兼容性:如果您的应用依赖于第三方服务或API,请确保这些接口与V2 SDK兼容,并按照预期工作。

    • 环境兼容性:在不同的操作系统和运行环境中测试您的应用,确保V2 SDK在各种环境下都能正常运行。

  4. 性能测试:

    在完成代码迁移后,必须对应用的性能进行全面评估:

    • 基准测试:建立性能基准,记录当前应用的响应时间、吞吐量等关键指标。

    • 对比分析:迁移完成后,使用相同的负载进行测试,比较新旧版本之间的性能差异,确保性能没有显著下降。

    • 调优:如果发现性能有所退步,可以通过调整配置参数、优化代码逻辑等方式进行改进。

V1V2版本差异汇总

差异点

V1

V2

Python版本要求

  • 支持Python 2.7及以上

  • 必须使用Python 3.8及以上

核心包导入

import oss2
import alibabacloud_oss_v2

签名算法

  • 默认使用V1签名算法

  • 默认使用V4签名算法

  • 必须配置区域(Region)

配置加载

  • 配置设置的方法分散在多处

  • 默认使用V1签名算法,区域(Region)非必填

  • 必须填写访问域名(Endpoint)

  • 简化了配置设置方式,全部迁移到 config下,可以以编程方式覆盖缺省配置

  • 默认使用V4签名算法,必须配置区域(Region)

  • 支持从区域(Region)信息构造访问域名(Endpoint), 当访问的是公网域名时,可以不设置Endpoint

创建客户端

  • Client的创建函数:oss2.Bucket()

  • Client的创建函数:alibabacloud_oss_v2.Client() 

API 调用方式

  • API接口未统一接口命名规范

  • 各基础接口采用了统一命名规范,具体规则请参见基础接口

预签名接口

  • 预签名接口:bucket.sign_url

  • 返回结果:预签名URL

  • 预签名接口:client.presign

  • 返回结果:预签名URL,HTTP方法,过期时间,被签名的请求头

断点续传接口

  • 断点续传上传接口:oss2.resumable_upload

  • 断点续传下载接口:oss2.resumable_download

  • 文件上传管理器:client.uploader

  • 文件下载管理器:client.downloader

  • 文件拷贝管理器:client.copier

重试机制

需要自定义重试逻辑

默认开启对HTTP请求的重试行为

常见迁移问题与解决方法

配置项变更相关问题

问题:在v2版本中,很多原来通过全局变量或函数参数设置的配置项现在需要通过Config对象设置。

解决方法

  • 梳理代码中所有配置相关的设置

  • 检查代码中是否有自定义的配置项,如超时设置、重试策略等

  • 将这些配置统一迁移到Config对象中

数据类型兼容性问题

问题:v2版本对数据类型的要求更加严格,特别是使用了类型注解。

解决方案

  • 检查代码中是否混合使用字符串和字节数据

  • 确保所有时间格式符合标准

  • 确保参数名称和类型符合新版SDK的要求

相关文档

关于Python SDK V1迁移到V2的更多详细内容,请参见开发者指南-迁移指南