All Products
Search
Document Center

Object Storage Service:File copy manager (Python SDK V2)

Last Updated:Mar 20, 2026

The Copier is a high-level copy interface in OSS SDK for Python V2 that automatically selects between CopyObject and multipart copy (UploadPartCopy) based on object size. Use it instead of calling those APIs directly — the Copier handles operation selection, part splitting, and concurrency for you.

Prerequisites

Before you begin, make sure you have:

  • Read permission on the source object

  • Read and write permissions on the destination bucket

  • OSS SDK for Python V2 installed (alibabacloud_oss_v2)

How it works

The Copier picks the copy operation based on object size and the multipart_copy_threshold setting:

Object sizeOperation usedNotes
Below threshold (default: 200 MiB)CopyObjectSingle-request copy; supports x-oss-metadata-directive and x-oss-tagging-directive. Suitable only for objects smaller than 5 GiB.
At or above thresholdUploadPartCopy (multipart copy)Parallel copy in parts; x-oss-metadata-directive and x-oss-tagging-directive are not supported — specify metadata and tags explicitly in the request
Cross-region copy is not supported. Source and destination buckets must be in the same region.
If a retention policy is configured on the source or destination bucket, the copy fails with: The object you specified is immutable.

Copy an object

The following example copies an object from a source bucket to a destination bucket using default settings.

import argparse
import alibabacloud_oss_v2 as oss

parser = argparse.ArgumentParser(description="copier sample")
parser.add_argument('--region', help='The region in which the bucket is located.', required=True)
parser.add_argument('--bucket', help='The name of the destination bucket.', required=True)
parser.add_argument('--endpoint', help='The domain names that other services can use to access OSS')
parser.add_argument('--key', help='The name of the destination object.', required=True)
parser.add_argument('--source_key', help='The name of the source object.', required=True)
parser.add_argument('--source_bucket', help='The name of the source bucket.', required=True)


def main():
    args = parser.parse_args()

    # Load AccessKey ID and AccessKey secret from environment variables.
    credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()

    cfg = oss.config.load_default()
    cfg.credentials_provider = credentials_provider
    cfg.region = args.region
    if args.endpoint is not None:
        cfg.endpoint = args.endpoint

    client = oss.Client(cfg)

    # Create a Copier instance with default settings.
    copier = client.copier()

    result = copier.copy(
        oss.CopyObjectRequest(
            bucket=args.bucket,                    # Destination bucket
            key=args.key,                          # Destination object key
            source_bucket=args.source_bucket,      # Source bucket
            source_key=args.source_key             # Source object key
        )
    )

    print(vars(result))


if __name__ == "__main__":
    main()
The sample code uses region cn-hangzhou and a public endpoint by default. If you access OSS from another Alibaba Cloud service in the same region, use an internal endpoint. For endpoint mappings, see Regions and endpoints.

API reference

client.copier(**kwargs) -> Copier

Creates a Copier instance. Pass configuration options as keyword arguments to apply them globally for all copy calls on that instance.

copier.copy(request, **kwargs) -> CopyResult

Copies an object. Pass configuration options as keyword arguments to override instance-level settings for that specific call.

CopyObjectRequest parameters

ParameterTypeDescription
bucketstrName of the destination bucket
keystrKey of the destination object
source_bucketstrName of the source bucket
source_keystrKey of the source object
forbid_overwritestrSpecifies whether to overwrite a destination object with the same key during the CopyObject operation.
taggingstrTags to apply to the destination object. Format: TagA=A&TagB=B
tagging_directivestrHow to handle tags on the destination object. Copy (default): copy tags from the source. Replace: use the tags specified in tagging.
progress_fncallableProgress callback. Called periodically with (bytes_transferred_in_this_chunk, total_bytes_written, total_bytes).

Configuration options

Set these at the Copier level (client.copier(...)) or per call (copier.copy(request, ...)). Per-call settings override instance-level settings.

ParameterTypeDefaultDescription
part_sizeint64 MiBSize of each part in a multipart copy
parallel_numint3Number of concurrent part copy tasks. This is a per-call limit, not a global limit.
multipart_copy_thresholdint64200 MiBObject size above which multipart copy is used
leave_parts_on_errorboolFalseSpecifies whether to retain the copied parts if the copy fails. By default, the copied parts are not retained.
disable_shallow_copyboolFalseSpecifies whether to disable shallow copy. By default, shallow copy is used.

Scenarios

Set part size and concurrency

Override part_size, parallel_num, and leave_parts_on_error per copy call:

import argparse
import alibabacloud_oss_v2 as oss

parser = argparse.ArgumentParser(description="copier sample")
parser.add_argument('--region', help='The region in which the bucket is located.', required=True)
parser.add_argument('--bucket', help='The name of the destination bucket.', required=True)
parser.add_argument('--endpoint', help='The domain names that other services can use to access OSS')
parser.add_argument('--key', help='The name of the destination object.', required=True)
parser.add_argument('--source_key', help='The name of the source object.', required=True)
parser.add_argument('--source_bucket', help='The name of the source bucket.', required=True)


def main():
    args = parser.parse_args()

    credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()

    cfg = oss.config.load_default()
    cfg.credentials_provider = credentials_provider
    cfg.region = args.region
    if args.endpoint is not None:
        cfg.endpoint = args.endpoint

    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
        ),
        part_size=1 * 1024 * 1024,    # 1 MiB per part
        parallel_num=5,                # 5 concurrent part copy tasks
        leave_parts_on_error=True,     # Keep parts on failure
    )

    print(vars(result))


if __name__ == "__main__":
    main()

Track copy progress

Pass a progress_fn callback to CopyObjectRequest to monitor copy progress:

import argparse
import alibabacloud_oss_v2 as oss

parser = argparse.ArgumentParser(description="copier sample")
parser.add_argument('--region', help='The region in which the bucket is located.', required=True)
parser.add_argument('--bucket', help='The name of the destination bucket.', required=True)
parser.add_argument('--endpoint', help='The domain names that other services can use to access OSS')
parser.add_argument('--key', help='The name of the destination object.', required=True)
parser.add_argument('--source_key', help='The name of the source object.', required=True)
parser.add_argument('--source_bucket', help='The name of the source bucket.', required=True)


def main():
    args = parser.parse_args()

    credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()

    cfg = oss.config.load_default()
    cfg.credentials_provider = credentials_provider
    cfg.region = args.region
    if args.endpoint is not None:
        cfg.endpoint = args.endpoint

    client = oss.Client(cfg)

    def _progress_fn(n, written, total):
        # n: bytes transferred in this chunk
        # written: total bytes written so far
        # total: total object size
        rate = int(100 * (float(written) / float(total)))
        print(f'\rCopy progress: {rate}% ', end='')

    copier = client.copier()

    result = copier.copy(
        oss.CopyObjectRequest(
            bucket=args.bucket,
            key=args.key,
            source_bucket=args.source_bucket,
            source_key=args.source_key,
            progress_fn=_progress_fn,    # Attach the progress callback
        )
    )

    print(vars(result))


if __name__ == "__main__":
    main()

What's next

  • For a full explanation of the Copier design and advanced options, see the Developer Guide.

  • For complete runnable sample code, see copier.py.