Mam pandy DataFrame, które chcę przesłać do nowego pliku CSV. Problem w tym, że nie chcę zapisywać pliku lokalnie przed przesłaniem go do s3. Czy istnieje metoda, taka jak to_csv, do bezpośredniego zapisu ramki danych do s3? Używam boto3.
Oto, co mam do tej pory:
import boto3
s3 = boto3.client('s3', aws_access_key_id='key', aws_secret_access_key='secret_key')
read_file = s3.get_object(Bucket, Key)
df = pd.read_csv(read_file['Body'])
# Make alterations to DataFrame
# Then export DataFrame to CSV through direct transfer to s3
df.to_csv('s3://mybucket/dfs/somedf.csv')
. stackoverflow.com/a/56275519/908886, aby uzyskać więcej informacji.Odpowiedzi:
Możesz użyć:
źródło
TypeError: unicode argument expected, got 'str'
błąd podczas używaniaStringIO
. UżyłemBytesIO
i działało idealnie. Uwaga: to było w Pythonie 2.7bucket
przedmiot jak to stworzyłeś?bucket
to miejsce, w którym przechowujesz obiekty na S3. Kod zakłada, że już utworzyłeś miejsce docelowe (myśl: katalog), w którym to ma być przechowywane. Zobacz dokumentację S3Możesz bezpośrednio użyć ścieżki S3. Używam Pandy 0.24.1
Informacje o wersji:
źródło
NoCredentialsError: Unable to locate credentials
. Jakieś sugestie?NotImplementedError: Text mode not supported, use mode='wb' and manage bytes
. jakieś sugestie?Lubię s3fs, który pozwala ci używać s3 (prawie) jak lokalnego systemu plików.
Możesz to zrobić:
s3fs
obsługuje tylkorb
iwb
tryby otwierania pliku, dlatego zrobiłem tobytes_to_write
.źródło
s3fs
nie wydaje się obsługiwać trybu dołączania.Oto bardziej aktualna odpowiedź:
Problem z StringIO polega na tym, że zżera twoją pamięć. Dzięki tej metodzie przesyłasz plik do s3, zamiast konwertować go na łańcuch, a następnie zapisywać do s3. Trzymanie ramki danych pandy i jej kopii w pamięci wydaje się bardzo nieefektywne.
Jeśli pracujesz w trybie ec2 natychmiast, możesz nadać mu rolę IAM, aby umożliwić zapisywanie go do s3, dzięki czemu nie musisz bezpośrednio przekazywać poświadczeń. Możesz jednak również połączyć się z zasobnikiem, przekazując dane uwierzytelniające do
S3FileSystem()
funkcji. Zobacz dokumentację: https://s3fs.readthedocs.io/en/latest/źródło
to_csv()
. wydaje się czystszą implementacją.botocore.exceptions.ClientError: An error occurred (AccessDenied) when calling the PutObject operation: Access Denied
... wykonałem nawet PUBLICZNY ODCZYT zasobnika i dodałem następujące akcje, w ramach mojego konkretnego konta IAM, w Polityce"Action": [ "s3:PutObject", "s3:PutObjectAcl", "s3:GetObject", "s3:GetObjectAcl", "s3:DeleteObject" ]
def send_to_bucket(df, fn_out, bucketname): csv_buffer = StringIO(); df.to_csv(csv_buffer); s3_resource = boto3.resource('s3'); s3_resource.Object(bucketname, fn_out).put(Body=csv_buffer.getvalue());
Jeśli przekażesz
None
jako pierwszy argument,to_csv()
dane zostaną zwrócone jako ciąg. Stamtąd łatwo jest przesłać to do S3 za jednym razem.Powinno być również możliwe przekazanie
StringIO
obiektuto_csv()
, ale użycie łańcucha będzie łatwiejsze.źródło
None
doto_csv()
i korzystania zwrócony ciąg, niż jest, aby stworzyćStringIO
obiekt, a następnie odczytać dane z powrotem na zewnątrz.Odkryłem, że można to zrobić
client
również, a nie tylkoresource
.źródło
Możesz również skorzystać z AWS Data Wrangler :
Zauważ, że podzieli się na kilka części, ponieważ przesyła go równolegle.
źródło
ponieważ używasz
boto3.client()
, spróbuj:źródło
Znalazłem bardzo proste rozwiązanie, które wydaje się działać:
Mam nadzieję, że to pomoże!
źródło
Czytałem csv z dwiema kolumnami z wiadra s3, a zawartość pliku csv umieściłem w pandas dataframe.
Przykład:
config.json
cls_config.json
cls_pandas.py
cls_s3.py
test.py
źródło