s3网址 - 获取存储桶名称和路径

时间:2017-03-07 06:06:32

标签: python boto3

我有一个包含aws s3 url的变量

s3://bucket_name/folder1/folder2/file1.json

我想在变量中获取bucket_name并在另一个变量中休息,即/folder1/folder2/file1.json。我尝试了正则表达式,可以像下面那样得到bucket_name,不确定是否有更好的方法。

m = re.search('(?<=s3:\/\/)[^\/]+', 's3://bucket_name/folder1/folder2/file1.json')
print(m.group(0))

我如何得到其余的东西,即folder1 / folder2 / file1.json?

我已检查是否有boto3功能从网址中提取bucket_name和密钥,但找不到它。

10 个答案:

答案 0 :(得分:42)

由于它只是一个普通网址,因此您可以使用urlparse获取网址的所有部分。

>>> from urlparse import urlparse
>>> o = urlparse('s3://bucket_name/folder1/folder2/file1.json', allow_fragments=False)
>>> o
ParseResult(scheme='s3', netloc='bucket_name', path='/folder1/folder2/file1.json', params='', query='', fragment='')
>>> o.netloc
'bucket_name'
>>> o.path
'/folder1/folder2/file1.json'

您可能必须从键中删除开始斜杠,如下一个答案所示。

o.path.lstrip('/')

随着Python 3 urlparse移至urllib.parse,请使用:

from urllib.parse import urlparse

这是一个负责处理所有细节的课程。

try:
    from urlparse import urlparse
except ImportError:
    from urllib.parse import urlparse


class S3Url(object):
    """
    >>> s = S3Url("s3://bucket/hello/world")
    >>> s.bucket
    'bucket'
    >>> s.key
    'hello/world'
    >>> s.url
    's3://bucket/hello/world'

    >>> s = S3Url("s3://bucket/hello/world?qwe1=3#ddd")
    >>> s.bucket
    'bucket'
    >>> s.key
    'hello/world?qwe1=3#ddd'
    >>> s.url
    's3://bucket/hello/world?qwe1=3#ddd'

    >>> s = S3Url("s3://bucket/hello/world#foo?bar=2")
    >>> s.key
    'hello/world#foo?bar=2'
    >>> s.url
    's3://bucket/hello/world#foo?bar=2'
    """

    def __init__(self, url):
        self._parsed = urlparse(url, allow_fragments=False)

    @property
    def bucket(self):
        return self._parsed.netloc

    @property
    def key(self):
        if self._parsed.query:
            return self._parsed.path.lstrip('/') + '?' + self._parsed.query
        else:
            return self._parsed.path.lstrip('/')

    @property
    def url(self):
        return self._parsed.geturl()

答案 1 :(得分:13)

对于那些喜欢我的人试图使用urlparse来提取密钥和存储桶以便用boto3创建对象。有一个重要的细节:从键的开头删除斜杠

from urlparse import urlparse
o = urlparse('s3://bucket_name/folder1/folder2/file1.json')
bucket = o.netloc
key = o.path
boto3.client('s3')
client.put_object(Body='test', Bucket=bucket, Key=key.lstrip('/'))

需要一段时间才能意识到因为boto3没有抛出任何异常。

答案 2 :(得分:7)

无需urllib或re(也处理前面的斜杠)的解决方案:

def split_s3_path(s3_path):
    path_parts=s3_path.replace("s3://","").split("/")
    bucket=path_parts.pop(0)
    key="/".join(path_parts)
    return bucket, key

运行:

bucket, key = split_s3_path("s3://my-bucket/some_folder/another_folder/my_file.txt")

返回:

bucket: my-bucket
key: some_folder/another_folder/my_file.txt

答案 3 :(得分:3)

如果您想使用正则表达式,可以执行以下操作:

>>> import re
>>> uri = 's3://my-bucket/my-folder/my-object.png'
>>> match = re.match(r's3:\/\/(.+?)\/(.+)', uri)
>>> match.group(1)
'my-bucket'
>>> match.group(2)
'my-folder/my-object.png'

这样做的好处是,您可以检查s3方案,而不是在那里允许任何内容。

答案 4 :(得分:3)

这是一个不错的项目:

s3path是aws s3服务的pathlib扩展

>>> from s3path import S3Path
>>> path = S3Path.from_uri('s3://bucket_name/folder1/folder2/file1.json')
>>> print(path.bucket)
'/bucket_name'
>>> print(path.key)
'folder1/folder2/file1.json'
>>> print(list(path.key.parents))
[S3Path('folder1/folder2'), S3Path('folder1'), S3Path('.')]

答案 5 :(得分:2)

只需一行内置字符串方法就可以轻松完成...

s3_filepath = "s3://bucket-name/and/some/key.txt"
bucket, key = s3_filepath.replace("s3://", "").split("/", 1)

答案 6 :(得分:1)

我做的最简单的是:

s = 's3://bucket/path1/path2/file.txt'
s1 = s.split('/', 3)
bucket = s1[2]
object_key = s1[3]

答案 7 :(得分:0)

这里是使用正则表达式的单行代码:

import re

s3_path = "s3://bucket/path/to/key"

bucket, key = re.match(r"s3:\/\/(.+?)\/(.+)", s3_path).groups()

答案 8 :(得分:0)

我使用以下正则表达式:

^(?:[s|S]3:\/\/)?([a-zA-Z0-9\._-]+)(?:\/)(.+)$

如果匹配,则 S3 解析部分如下:

  • 匹配 group1 => S3 存储桶名称
  • 匹配 group2 => S3 对象名称

此模式处理带或不带 s3:// uri 前缀的存储桶路径。

如果要允许其他合法存储桶名称字符,请根据需要修改模式的 [a-zA-Z0-9_-] 部分以包含其他字符。

完整的 JS 示例(以 Typescript 形式)

const S3_URI_PATTERN = '^(?:[s|S]3:\\/\\/)?([a-zA-Z0-9\\._-]+)(?:\\/)(.+)$';

export interface S3UriParseResult {
  bucket: string;
  name: string;
}

export class S3Helper {
  /**
   *
   * @param uri
   */
  static parseUri(uri: string): S3UriParseResult {
    const re = new RegExp(S3_URI_PATTERN);
    const match = re.exec(uri);
    if (!match || (match && match.length !== 3)) {
      throw new Error('Invalid S3 object URI');
    }
    return {
      bucket: match[1],
      name: match[2],
    };
  }
}

答案 9 :(得分:0)

最近的一个选项是使用 cloudpathlib,它为云服务(包括 S3、Google Cloud Storage 和 Azure Blob Storage)上的文件实现 pathlib 函数。

除了这些功能之外,您还可以轻松获取 S3 路径的存储桶和密钥。

from cloudpathlib import S3Path

path = S3Path("s3://bucket_name/folder1/folder2/file1.json")

path.bucket
#> 'bucket_name'

path.key
#> 'folder1/folder2/file1.json'