web-dev-qa-db-fra.com

URL s3 - obtenir le nom et le chemin du compartiment

J'ai une variable qui a l'url aws s3

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

Je veux obtenir le bucket_name dans une variable et reposer c'est-à-dire /folder1/folder2/file1.json dans une autre variable. J'ai essayé les expressions régulières et j'ai pu obtenir le bucket_name comme ci-dessous, je ne sais pas s'il y a une meilleure façon.

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

Comment puis-je obtenir le reste, c'est-à-dire dossier1/dossier2/fichier1.json?

J'ai vérifié s'il existe une fonctionnalité boto3 pour extraire le bucket_name et la clé de l'URL, mais je ne l'ai pas trouvée.

41
Lijju Mathew

Comme il ne s'agit que d'une URL normale, vous pouvez utiliser urlparse pour obtenir toutes les parties de l'URL.

>>> 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'

Vous devrez peut-être supprimer la barre oblique de début de la clé, comme le suggère la réponse suivante.

o.path.lstrip('/')

Avec Python 3 urlparse déplacé vers urllib.parse alors utilisez:

from urllib.parse import urlparse

Voici un cours qui s'occupe de tous les détails.

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()
63
kichik

Pour ceux qui comme moi essayaient d'utiliser urlparse pour extraire la clé et le bucket afin de créer un objet avec boto3. Il y a un détail important: supprimer la barre oblique du début de la clé

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('/'))

Il a fallu un certain temps pour réaliser cela, car boto3 ne lève aucune exception.

16
Mikhail Sirotenko

Une solution qui fonctionne sans urllib ou re (gère également la barre oblique précédente):

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

Courir:

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

Retour:

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

Si vous souhaitez le faire avec des expressions régulières, vous pouvez effectuer les opérations suivantes:

>>> 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'

Cela a l'avantage que vous pouvez vérifier le s3 schéma plutôt que d'y autoriser quoi que ce soit.

6
Alec Hewitt

Ici, c'est comme une ligne à l'aide de regex:

import re

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

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