boto3用法

安装

pip install boto3
pip install awscli
aws configure

根据提示输入access_key_id, secret_access_keyregion。默认存储位置为:~/.aws/credentials

[default]
aws_access_key_id = YOUR_ACCESS_KEY
aws_secret_access_key = YOUR_SECRET_KEY

region的存储位置为~/.aws/config:

[default]
region=us-east-1

快速开始

import boto3

# Let's use Amazon S3
s3 = boto3.resource('s3')
# Print out bucket names
for bucket in s3.buckets.all():
    print(bucket.name)
# Upload a new file
data = open('test.jpg', 'rb')
s3.Bucket('my-bucket').put_object(Key='test.jpg', Body=data)

使用Bucket

创建bucket

import logging
import boto3
from botocore.exceptions import ClientError

def create_bucket(bucket_name):
""" Create an Amazon S3 bucket

:param bucket_name: Unique string name
:return: True if bucket is created, else False
"""

s3 = boto3.client('s3')
try
    s3.create_bucket(Bucket=bucket_name)
except ClientError as e:
    logging.error(e)
    return False
return True

列出bucket

# Retrieve the list of existing buckets
s3 = boto3.client('s3')
response = s3.list_buckets()

# Output the bucket names
print('Existing buckets:')
for bucket in response['Buckets']:
    print(f'  {bucket["Name"]}')

上传文件

基本用法

s3提供了两种文件上传方式:upload_file()和upload_file_obj()。upload_file()会把一个大文件拆分成若干个chunk并行上传,因此upload_file()传输速率较快,它适用于上传内容已经确定的文件。upload_file_obj()可用于单线程上传一个二进制流。
upload_file()例子:

import logging
import boto3
from botocore.exceptions import ClientError


def upload_file(file_name, bucket, object_name=None):
    """Upload a file to an S3 bucket

    :param file_name: File to upload
    :param bucket: Bucket to upload to
    :param object_name: S3 object name. If not specified then file_name is used
    :return: True if file was uploaded, else False
    """

    # If S3 object_name was not specified, use file_name
    if object_name is None:
        object_name = file_name

    # Upload the file
    s3_client = boto3.client('s3')
    try:
        response = s3_client.upload_file(file_name, bucket, object_name)
    except ClientError as e:
        logging.error(e)
        return False
    return True

upload_file_obj()例子:

s3 = boto3.client('s3')
with open("FILE_NAME", "rb") as f:
    s3.upload_fileobj(f, "BUCKET_NAME", "OBJECT_NAME")

upload_file_obj的文件参数只能是rb模式打开的文件。

Client、Bucket、Object三个类型都提供了upload_file()和upload_file_obj()两个函数,每个类型提供的同一函数功能都是等价的,并无优劣之分,可以随意调用三个对象的上传文件函数。

ExtraArgs

ExtraArgs提供了上传文件的其它参数,这些参数可用于控制上传文件的读写权限、meta信息等。S3Transfer是一个非常重要的对象,它定义了传输过程中的许多参数,在
boto3.s3.transfer.S3Transfer.ALLOWED_UPLOAD_ARGS中,定义了ExtraArgs可用的参数列表。

s3.upload_file(
    'FILE_NAME', 'BUCKET_NAME', 'OBJECT_NAME',
    ExtraArgs={'Metadata': {'mykey': 'myvalue'}}
)
s3.upload_file(
    'FILE_NAME', 'BUCKET_NAME', 'OBJECT_NAME',
    ExtraArgs={'ACL': 'public-read'}
)
s3.upload_file(
    'FILE_NAME', 'BUCKET_NAME', 'OBJECT_NAME',
    ExtraArgs={
        'GrantRead': 'uri="http://acs.amazonaws.com/groups/global/AllUsers"',
        'GrantFullControl': 'id="01234567890abcdefg"',
    }
)

上传过程的回调函数

一边上传一边打印上传进度可以通过实现Callback回调来实现。

s3.upload_file(
    'FILE_NAME', 'BUCKET_NAME', 'OBJECT_NAME',
    Callback=ProgressPercentage('FILE_NAME')
)

ProgressPercentage

import os
import sys
import threading

class ProgressPercentage(object):

    def __init__(self, filename):
        self._filename = filename
        self._size = float(os.path.getsize(filename))
        self._seen_so_far = 0
        self._lock = threading.Lock()

    def __call__(self, bytes_amount):
        # To simplify, assume this is hooked up to a single filename
        with self._lock:
            self._seen_so_far += bytes_amount
            percentage = (self._seen_so_far / self._size) * 100
            sys.stdout.write(
                "\r%s  %s / %s  (%.2f%%)" % (
                    self._filename, self._seen_so_far, self._size,
                    percentage))
            sys.stdout.flush()

下载文件

下载文件和上传文件几乎是完全对称的,Client、Bucket、Object三个对象提供了download_file()、download_file_obj()。download_file()是并行的,download_file_obj()是串行的,这两个函数同样提供了ExtraArgs和Callback参数。boto3.s3.transfer.S3Transfer.ALLOWED_DOWNLOAD_ARGS描述了下载过程的ExtraArgs的可用参数。

import boto3

s3 = boto3.client('s3')
s3.download_file('BUCKET_NAME', 'OBJECT_NAME', 'FILE_NAME')

with open('FILE_NAME', 'wb') as f:
    s3.download_fileobj('BUCKET_NAME', 'OBJECT_NAME', f)

传输配置

在上传文件、下载文件、复制文件过程中,AWS SDK会自动管理重试等网络配置。默认的网络配置可适用于大多数情况,只有特殊情境下才需要修改传输配置。
传输配置封装在 boto3.s3.transfer.TransferConfig对象中,upload_file()等函数都有一个Config参数接受一个TransferConfig对象。

修改multipar阈值

import boto3
from boto3.s3.transfer import TransferConfig

# Set the desired multipart threshold value (5GB)
GB = 1024 ** 3
config = TransferConfig(multipart_threshold=5*GB)

# Perform the transfer
s3 = boto3.client('s3')
s3.upload_file('FILE_NAME', 'BUCKET_NAME', 'OBJECT_NAME', Config=config)

设置并发数

对于upload_file()和download_file()默认启用多线程下载,为了减少带宽或者增加带宽,可以通过传输配置来控制。

# To consume less downstream bandwidth, decrease the maximum concurrency
config = TransferConfig(max_concurrency=5)

# Download an S3 object
s3 = boto3.client('s3')
s3.download_file('BUCKET_NAME', 'OBJECT_NAME', 'FILE_NAME', Config=config)

设置并发的实现方式

在boto3中,并发是通过多线程来实现的。如果不使用线程就没法实现并发,max_concurrency参数会被忽略掉。

# Disable thread use/transfer concurrency
config = TransferConfig(use_threads=False)

s3 = boto3.client('s3')
s3.download_file('BUCKET_NAME', 'OBJECT_NAME', 'FILE_NAME', Config=config)

将一个Bucket作为一个静态服务

获取一个桶的静态服务配置

import boto3

# Retrieve the website configuration
s3 = boto3.client('s3')
result = s3.get_bucket_website('BUCKET_NAME')

设置一个桶的静态服务配置

# Define the website configuration
website_configuration = {
    'ErrorDocument': {'Key': 'error.html'},
    'IndexDocument': {'Suffix': 'index.html'},
}

# Set the website configuration
s3 = boto3.client('s3')
s3.put_bucket_website('BUCKET_NAME', website_configuration)

删除一个桶的网站配置

# Delete the website configuration
s3 = boto3.client('s3')
s3.delete_bucket_website('BUCKET_NAME')

获取一个Bucket的权限列表

import boto3

# Retrieve a bucket's ACL
s3 = boto3.client('s3')
result = s3.get_bucket_acl(Bucket='my-bucket')
print(result)

presigned URL

分享一个Object

import logging
import boto3
from botocore.exceptions import ClientError


def create_presigned_url(bucket_name, object_name, expiration=3600):
    """Generate a presigned URL to share an S3 object

    :param bucket_name: string
    :param object_name: string
    :param expiration: Time in seconds for the presigned URL to remain valid
    :return: Presigned URL as string. If error, returns None.
    """

    # Generate a presigned URL for the S3 object
    s3_client = boto3.client('s3')
    try:
        response = s3_client.generate_presigned_url('get_object',
                                                    Params={'Bucket': bucket_name,
                                                            'Key': object_name},
                                                    ExpiresIn=expiration)
    except ClientError as e:
        logging.error(e)
        return None

    # The response contains the presigned URL
    return response

直接使用GET请求这个URL:

import requests    # To install: pip install requests

url = create_presigned_url('BUCKET_NAME', 'OBJECT_NAME')
if url is not None:
    response = requests.get(url)

其它技巧

  • 生成一个URL,这个URL可以自动执行某个函数,从而可以实现动态查看某个Bucket下面的目录
  • 生成一个可以上传文件的URL

桶策略

设计

  1. boto3提供了两个级别的接口来访问AWS服务:High Level的Resource级别的接口,Low Level的Client接口。
    Client级别的接口返回Dictionary来表示查询到的资源信息,Resource级别的接口对Client级别的接口进行了面向对象的封装,接口的返回值大部分都是Resource对象(如果返回值是某个Resource的信息的话),我们可以对返回的对象再进行操作(比如删除,修改等)。

  2. session
    session是对一组configuration的抽象表达,通过同一session调用的所有api共享一组configuration. session也是访问所有API的入口。
    所以一般通过如下代码来得到Resource级别的API对象和Client级别的API对象:
    res = boto3.resource('service name')
    client = boto3.client('service name')
  3. resource
    这是Resource级别接口里面的概念,Resource分为Service Resource和Individual Resource. Service Resource表示某个服务,而Individual Resource表示某个服务里面的资源

3.1 resource identifier
Resource的唯一标示符,一般就是id或是url。很明显Service Resource不需要identifier,因为它是通过名字标识(例如:'ec2')

3.2 attribute
其实就是Resource的属性

3.3 action
就是Resource支持的操作

3.4 subResource
Resource的子级Resource,可以通过identifier来获取Resource对象

3.5 collection
Resource的子级Resource的集合,可以对collection进行查询,筛选等(对AWS的网络请求只有在collection执行操作(遍历,转换为list, 批量处理)的时候才会产生并发出)

  1. 一般使用方式

4.1 Resource级别

var serviceRes = boto3.resource('ec2') //得到Service Resource
var instance = serviceRes.create_instances(**kwargs) //执行Service Resource级别的操作
var instance = serviceRes.Instance(id) // 通过identifier得到Sub Resource(Individual Resource)

var instances = serviceRes.instances.filter(filter) // 通过filter得到一个Sub Resource的collection

instance.start() //执行Sub Resource上的操作

4.2 Client级别

var ec2Client = boto3.client('ec2') //得到对应服务的client
ec2Client.run_instances(**kwargs) //执行操作

class boto3.session.Session
(aws_access_key_id=None, aws_secret_access_key=None, aws_session_token=None,region_name=None,botocore_session=None, profile_name=None)

ssession 存储配置状态并允许你创建服务客户端和资源
参数:

× aws_access_key_id(字符串) -- AWS access key ID
× aws_secret_access_key(字符串) -- AWS secret access key
× aws_session_token(字符串) -- AWS 临时session token
× region_name(字符串) -- 当创建新的连接时的默认区域
× botocore_session(botocore.session_Session) -- 使用这个Botocore session 而不是创建一个 new dafault one
× profile_name(字符串) -- 配置文件的名字去使用,如果没有给出,就用默认的profile

创建一个连接:

boto3

import boto3
s3 = boto3.resource('s3')

创建一个Bucket
在boto3,所有的行为必须通过关键字参数传递进去,并且,一个bucket的配置必须手动配置

Boto 3

s3.create_bucket(Bucket='mybucket')
s3.create_bucket(Bucket='mybucket',CreateBucketConfiguration={'LocationConstraint': 'us-west-1'})

访问一个bucket
用Boto3的resource 去获得一个bucket是非常方便的,但不会自动验证bucket是否真的存在

Boto 3

import botocore
bucket = s3.Bucket('mybucket')
exists = True
try:
s3.meta.client.head_bucket(Bucket='mybucket')
except botocore.exceptions.ClientError as e:
# If a client error is thrown, then check that it was a 404 error.
# If it was a 404 error, then the bucket does not exist.
error_code = int(e.response['Error']['Code'])
if error_code == 404:
exists = False

available_profiles
session 证书可用的配置文件
client(service_name,region_name=None, api_version=None,use_ssl=True, verify=None,endpoint=None, aws_acess_key_id=None, aws_secret_key=None,aws_session_token=None config=None)
通过名字去创建一个低等级的服务客户端
参数

service_name(字符串) -- 服务器的名字,例如 's3' 或者 'ec2',可以通过get_available_services() 去获得有效的一串服务器
region_name(字符串) -- 与客户端相关联的区域名字,一个客户端关联单个区域
api_version(字符串) -- 要用的API版本,默认的,当创建一个新的client,botocore将使用最新的API version.如果想用客户端的之前的API 版本,你只需要指明这个参数。
use_ssl(boolean) -- 是否使用SSL,默认是使用SSL,注意:不是所有的服务支持no-ssl 连接
verify(字符串或者布尔值) -- 是否去认证ssl证书,默认SSL证书需要认证,你可以提供以下的值 False -不去认证SSL证书的有效性,SSL仍然被使用,但是SSL 证书不会被认证 path/to/cert/bundle.pem -要使用的CA证书包的文件名
endpoint_url -为构建的client去用的全的url,正常情况下,botocore会自动构建一个适合的URL去用来和服务器交流。你可以去指定一个全的URL,(including http/https 模型)去重写这个行为,如果这个value提供了,那use_ssl将被忽略
aws_access_key_id(字符串) - 完全的可选项,如果不提供, 将用session的配置,
aws_secret_access_key(字符串) - 与上面参数类似,可由session自动提供
aws_session_token(字符串) - 与上面类似
config(boto.client.Config) 高级的客户端配置选项

返回值
Service client instance
events
session的事件发射器

get_available_partitions()
列出可用的分区
返回类型:列表
返回值:返回一个含有分区名字的列表

__get_available_regions(service_name, partition_name='aws', allow_non_regional=False)
列出一个特定分区的区域和端点名字
返回值:一个包含端点名字的列表 例如["us-east-1"]
get_available_resources()
获得一个可用的能够通过Session.resources()加载为资源客户端的服务列表,
返回类型:列表
返回值:
服务名字的列表
get_available_services()
获得一个能通过Session.client() 加载为低等级客户端的服务
返回类型:列表
返回值:服务名字的列表
resource(service_name, region_name=None,api_verson=None, use_ssl=True, verify=None, endpoint_url=None, aws_access_key_id=None, aws_secret_access_key=None, aws_session_token=None, config=None)
通过名字创建一个资源服务客户端
返回值:
ServiceResource 的子类

使用技巧

content-range随机读取,相当于fseek
https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.16

参考资料

https://boto3.amazonaws.com/v1/documentation/api/latest/index.html

猜你喜欢

转载自www.cnblogs.com/weiyinfu/p/10993205.html
今日推荐