Tengo una variable que tiene la url aws s3
s3://bucket_name/folder1/folder2/file1.jsonQuiero obtener el nombre del depósito en una variable y descansar, es decir, /carpeta1/carpeta2/archivo1.json en otra variable. Probé las expresiones regulares y pude obtener el bucket_name como se muestra a continuación, no estoy seguro de si hay una mejor manera.
m = re.search('(?<=s3:\/\/)[^\/]+', 's3://bucket_name/folder1/folder2/file1.json') print(m.group(0))¿Cómo obtengo el resto, es decir, carpeta1/carpeta2/archivo1.json?
Verifiqué si hay una función de boto3 para extraer el nombre del depósito y la clave de la URL, pero no pude encontrarla.
Dado que es solo una URL normal, puede usar urlparse para obtener todas las partes de la 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'Es posible que deba eliminar la barra inclinada inicial de la clave como sugiere la siguiente respuesta.
o.path.lstrip('/') Con Python 3 urlparse se movió a urllib.parse , así que use:
from urllib.parse import urlparseAquí hay una clase que cuida todos los detalles.
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()Una solución que funciona sin urllib o re (también maneja la barra diagonal anterior):
def split_s3_path(s3_path): path_parts=s3_path.replace("s3://","").split("/") bucket=path_parts.pop(0) key="/".join(path_parts) return bucket, keyCorrer:
bucket, key = split_s3_path("s3://my-bucket/some_folder/another_folder/my_file.txt")Devoluciones:
bucket: my-bucket key: some_folder/another_folder/my_file.txtPara aquellos que, como yo, intentaban usar urlparse para extraer la clave y el cubo para crear un objeto con boto3. Hay un detalle importante: eliminar la barra diagonal del principio de la tecla
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('/'))Me tomó un tiempo darme cuenta de eso porque boto3 no arroja ninguna excepción.