Pouvez-vous télécharger S3 à l'aide d'un flux plutôt que d'un fichier local?
J'ai besoin de créer un fichier CSV et de les télécharger sur un compartiment S3. Depuis que je suis de créer le fichier à la volée, ce serait mieux si je pouvais l'écrire directement à S3 seau comme il est en cours de création plutôt que d'écrire la totalité du fichier en local, puis d'envoyer le fichier à la fin.
Est-il un moyen de faire cela? Mon projet est en Python et je suis assez nouveau dans la langue. Voici ce que j'ai essayé jusqu'à présent:
import csv
import csv
import io
import boto
from boto.s3.key import Key
conn = boto.connect_s3()
bucket = conn.get_bucket('dev-vs')
k = Key(bucket)
k.key = 'foo/foobar'
fieldnames = ['first_name', 'last_name']
writer = csv.DictWriter(io.StringIO(), fieldnames=fieldnames)
k.set_contents_from_stream(writer.writeheader())
J'ai reçu ce message d'erreur: BotoClientError: s3 ne prend pas en charge un transfert
Mise à JOUR: j'ai trouvé une façon d'écrire directement à la S3, mais je ne peux pas trouver un moyen pour effacer le tampon sans réellement supprimer les lignes que j'ai déjà écrit. Ainsi, par exemple:
conn = boto.connect_s3()
bucket = conn.get_bucket('dev-vs')
k = Key(bucket)
k.key = 'foo/foobar'
testDict = [{
"fieldA": "8",
"fieldB": None,
"fieldC": "888888888888"},
{
"fieldA": "9",
"fieldB": None,
"fieldC": "99999999999"}]
f = io.StringIO()
fieldnames = ['fieldA', 'fieldB', 'fieldC']
writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writeheader()
k.set_contents_from_string(f.getvalue())
for row in testDict:
writer.writerow(row)
k.set_contents_from_string(f.getvalue())
f.close()
Écrit 3 lignes dans le fichier, mais je ne suis pas en mesure de libérer de la mémoire pour écrire un fichier de grande taille. Si j'ajoute:
f.seek(0)
f.truncate(0)
de la boucle, alors que la dernière ligne du fichier est écrit. Est-il possible de libérer des ressources sans supprimer des lignes du fichier?
- Même si vous pourriez écrire à S3 comme vous voulez, je ne le recommanderais pas en raison de la cohérence des défis. Pourquoi pensez-vous qu'il serait mieux de ne pas écrire localement? Voulez-vous une partielle S3 objet si il y a une exception ou une question? Je présume pas.
- J'étais à la recherche d'écrire directement pour être un peu plus efficace. Essentiellement, si j'écris le fichier localement, et de les télécharger, je suis en ajoutant le téléchargement comme une étape supplémentaire, et le nettoyage du fichier local. Je ne me dérange pas d'avoir un dossier incomplet - je pourrais avoir un dossier incomplet si je l'ai écrit localement trop. Le système va être idempotent et supprimer un fichier dans un état d'erreur, ou de continuer.
Vous devez vous connecter pour publier un commentaire.
J'ai trouvé une solution à ma question, que je poste ici au cas où quelqu'un d'autre est intéressé. J'ai décidé de faire ce que les pièces dans un multipart télécharger. Vous ne pouvez pas le flux de S3. Il y a aussi un paquet de modifications de votre fichier de transmission en continu à un multipart de téléchargement que j'ai utilisé: Smart Open.
StringIO.StringIO()
au lieu deio.StringIO()
, sinon vous recevrez une erreur de codageSelon docs il est possible
nous pouvons donc utiliser
StringIO
dans la manière ordinaireMise à jour: smart_open lib de @curieux réponse est la meilleure solution
StringIO
objet au lieu de fichierboto
sources et je vois, il doit calculer la somme de contrôle MD5 de chaque fichier envoyé. Cela signifie que le flux doit être "adressable" au moins. J'ai non-adressable stream que j'ai lu de mongodb et je ne peux pas revenir en arrière le flux de données facilement. Le recommandé icismart_open
permet d'utiliser les flux, mais il utilise une mémoire tampon interne et ensuite utiliser 'multipart de téléchargement avecboto
trop. Techniquement, il est possible d'utiliser des fichiers comme des flots, mais être prêt qu'il peut exiger beaucoup de mémoire. L'idée de flux est faible utilisation de la mémoire à télécharger (probablement) sans fin flux de données.smart_open
œuvres. Et il semble que c'est le seul moyen de télécharger ces fichiers. Vous télécharger de gros fichiers en plus petits morceaux. Je n'avais pas l'appeler " flux de téléchargement, il suffit de morceau de téléchargement.