J'essaie de lire certains journaux d'un processus Hadoop que j'exécute dans AWS. Les journaux sont stockés dans un dossier S3 et ont le chemin suivant.
bucketname = nom clé = y/z/stderr.gz Ici Y est l'ID du cluster et z est un nom de dossier. Ces deux agissent comme des dossiers (objets) dans AWS. Le chemin complet est donc comme x/y/z/stderr.gz.
Maintenant, je veux décompresser ce fichier .gz et lire le contenu du fichier. Je ne veux pas télécharger ce fichier sur mon système veut enregistrer le contenu dans une variable python.
C'est ce que j'ai essayé jusqu'à présent.
bucket_name = "name"
key = "y/z/stderr.gz"
obj = s3.Object(bucket_name,key)
n = obj.get()['Body'].read()
Cela me donne un format qui n'est pas lisible. J'ai aussi essayé
n = obj.get()['Body'].read().decode('utf-8')
ce qui donne une erreur le codec utf8 ne peut pas décoder l'octet 0x8b en position 1: octet de démarrage invalide.
J'ai aussi essayé
gzip = StringIO(obj)
gzipfile = gzip.GzipFile(fileobj=gzip)
content = gzipfile.read()
Cela renvoie une erreur IOError: Pas un fichier compressé
Vous ne savez pas comment décoder ce fichier .gz.
Modifier - J'ai trouvé une solution. Nécessaire pour passer n dedans et utiliser BytesIO
gzip = BytesIO(n)
@Amit, j'essayais de faire la même chose pour tester le décodage d'un fichier, et j'ai fait exécuter votre code avec quelques modifications. J'ai juste dû supprimer la fonction def, le retour et renommer la variable gzip, car ce nom est utilisé.
import json
import boto3
from io import BytesIO
import gzip
try:
s3 = boto3.resource('s3')
key='YOUR_FILE_NAME.gz'
obj = s3.Object('YOUR_BUCKET_NAME',key)
n = obj.get()['Body'].read()
gzipfile = BytesIO(n)
gzipfile = gzip.GzipFile(fileobj=gzipfile)
content = gzipfile.read()
print(content)
except Exception as e:
print(e)
raise e
Vous pouvez utiliser AWS S3 SELECT Object Content pour lire le contenu gzip
S3 Select est une capacité Amazon S3 conçue pour extraire uniquement les données dont vous avez besoin d'un objet, ce qui peut considérablement améliorer les performances et réduire le coût des applications qui ont besoin d'accéder aux données dans S3.
Amazon S3 Select fonctionne sur les objets stockés au format Apache Parquet, les tableaux JSON et la compression BZIP2 pour les objets CSV et JSON.
Réf: https://docs.aws.Amazon.com/AmazonS3/latest/dev/selecting-content-from-objects.html
from io import StringIO
import boto3
import pandas as pd
bucket = 'my-bucket'
prefix = 'my-prefix'
client = boto3.client('s3')
for object in client.list_objects_v2(Bucket=bucket, Prefix=prefix)['Contents']:
if object['Size'] <= 0:
continue
print(object['Key'])
r = client.select_object_content(
Bucket=bucket,
Key=object['Key'],
ExpressionType='SQL',
Expression="select * from s3object",
InputSerialization = {'CompressionType': 'GZIP', 'JSON': {'Type': 'DOCUMENT'}},
OutputSerialization = {'CSV': {'QuoteFields': 'ASNEEDED', 'RecordDelimiter': '\n', 'FieldDelimiter': ',', 'QuoteCharacter': '"', 'QuoteEscapeCharacter': '"'}},
)
for event in r['Payload']:
if 'Records' in event:
records = event['Records']['Payload'].decode('utf-8')
payloads = (''.join(r for r in records))
try:
select_df = pd.read_csv(StringIO(payloads), error_bad_lines=False)
for row in select_df.iterrows():
print(row)
except Exception as e:
print(e)
Lire le fichier d'extension Bz2 depuis aws s3 en python
import json
import boto3
from io import BytesIO
import bz2
try:
s3 = boto3.resource('s3')
key='key_name.bz2'
obj = s3.Object('bucket_name',key)
nn = obj.get()['Body'].read()
gzipfile = BytesIO(nn)
content = bz2.decompress(gzipfile.read())
content = content.split('\n')
print len(content)
except Exception as e:
print(e)
Actuellement, le fichier peut être lu comme
role = 'role name'
bucket = 'bucket name'
data_key = 'data key'
data_location = 's3://{}/{}'.format(bucket, data_key)
data = pd.read_csv(data_location,compression='gzip', header=0, sep=',', quotechar='"')
Tout comme ce que nous faisons avec les variables, les données peuvent être conservées sous forme d'octets dans un tampon en mémoire lorsque nous utilisons les opérations Byte IO) du module io.
Voici un exemple de programme pour le démontrer:
mport io
stream_str = io.BytesIO(b"JournalDev Python: \x00\x01")
print(stream_str.getvalue())
La fonction getvalue()
prend la valeur du tampon sous forme de chaîne.
Donc, la réponse @ Jean-FrançoisFabre est correcte, et vous devez utiliser
gzip = BytesIO(n)
Pour plus d'informations, lisez le document suivant: