2011-02-14 6 views
16

Je veux écrire un script Python qui va lire et écrire des fichiers à partir de s3 en utilisant leur URL, par exemple: 's3:/mybucket/file'. Il devrait fonctionner localement et dans le nuage sans aucun changement de code. Y a-t-il un moyen de faire cela?Comment puis-je accéder aux fichiers s3 en Python en utilisant les URL?

Edit: Il y a quelques bonnes suggestions ici, mais ce que je veux vraiment quelque chose qui me permet de le faire:

myfile = open("s3://mybucket/file", "r") 

puis utilisez cet objet de fichier comme tout autre objet de fichier. Ce serait vraiment cool. Je pourrais écrire quelque chose comme ça pour moi si ça n'existe pas. Je pourrais construire cette couche d'abstraction sur simples3 ou boto.

+0

Avez-vous besoin que les fichiers soient privés ou juste le cas le plus simple? –

+0

Ils n'ont pas besoin d'être privés. Je veux juste pouvoir utiliser les URL pour y accéder dans mon code. Je suppose que ce que je cherche vraiment, c'est une couche d'abstraction qui me permette de travailler avec des fichiers utilisant des URLs, qu'il s'agisse d'une bibliothèque Python ou de FUSE mais qui supporte les URL au lieu des chemins de fichiers locaux. –

Répondre

2

Je ne l'ai pas vu quelque chose qui fonctionnerait directement avec S3 urls, mais vous pouvez utiliser un S3 access library (simples3 semble décent) et une manipulation de chaîne simple:

>>> url = "s3:/bucket/path/" 
>>> _, path = url.split(":", 1) 
>>> path = path.lstrip("/") 
>>> bucket, path = path.split("/", 1) 
>>> print bucket 
'bucket' 
>>> print path 
'path/' 
+0

C'est un peu ce que je pense. En plus de résoudre le chemin s3 peut-être quelques routines supplémentaires à la lecture/écriture abstraite à des compartiments. –

1

Vous pouvez utiliser Boto Python API pour accéder à S3 par python. C'est une bonne bibliothèque. Une fois que vous faites l'installation de Boto, suivant l'échantillon programe travaillera pour vous

>>> k = Key(b) 
>>> k.key = 'yourfile' 
>>> k.set_contents_from_filename('yourfile.txt') 

Vous pouvez trouver plus d'informations ici http://boto.cloudhackers.com/s3_tut.html#storing-data

+0

La question est en fait d'utiliser des URL commençant par s3: // ou non (fichiers locaux), de sorte que S3 et un système de fichiers local puissent être accédés de manière uniforme par le programme Python. – EOL

1

http://s3tools.org/s3cmd fonctionne assez bien et soutenir le s3: // forme de la structure d'URL vouloir. Il fait l'affaire sur Linux et Windows. Si vous avez besoin d'une API native pour appeler à partir d'un programme python, alors http://code.google.com/p/boto/ est un meilleur choix.

+1

J'utilise s3cmd depuis la ligne de commande (utilisation interactive/manuelle) tout le temps - c'est un bon outil. Cependant, soyez averti qu'il ne se comporte pas comme un outil de ligne de commande Unix normal - ne renvoie pas un code d'erreur indiquant le succès ou l'échec, il ne peut donc pas être utilisé dans les scripts. –

10

Pour l'ouverture, il devrait être aussi simple que:

import urllib 
opener = urllib.URLopener() 
myurl = "https://s3.amazonaws.com/skyl/fake.xyz" 
myfile = opener.open(myurl) 

Cela fonctionne avec s3 si le fichier est public.

Pour écrire un fichier en utilisant Boto, il va un petit quelque chose comme ceci:

from boto.s3.connection import S3Connection 
conn = S3Connection(AWS_KEY, AWS_SECRET) 
bucket = conn.get_bucket(BUCKET) 
destination = bucket.new_key() 
destination.name = filename 
destination.set_contents_from_file(myfile) 
destination.make_public() 

Lemme savoir si cela fonctionne pour vous :)

3

Here's how they do dans awscli:

def find_bucket_key(s3_path): 
    """ 
    This is a helper function that given an s3 path such that the path is of 
    the form: bucket/key 
    It will return the bucket and the key represented by the s3 path 
    """ 
    s3_components = s3_path.split('/') 
    bucket = s3_components[0] 
    s3_key = "" 
    if len(s3_components) > 1: 
     s3_key = '/'.join(s3_components[1:]) 
    return bucket, s3_key 


def split_s3_bucket_key(s3_path): 
    """Split s3 path into bucket and key prefix. 
    This will also handle the s3:// prefix. 
    :return: Tuple of ('bucketname', 'keyname') 
    """ 
    if s3_path.startswith('s3://'): 
     s3_path = s3_path[5:] 
    return find_bucket_key(s3_path) 

Ce que vous pourriez simplement utiliser avec un code comme celui-ci

from awscli.customizations.s3.utils import split_s3_bucket_key 
import boto3 
client = boto3.client('s3') 
bucket_name, key_name = split_s3_bucket_key(
    's3://example-bucket-name/path/to/example.txt') 
response = client.get_object(Bucket=bucket_name, Key=key_name) 

Ceci n'aborde pas l'objectif d'interaction avec une clé s3 comme file like object mais c'est un pas dans cette direction.

Questions connexes