Próbowałem skompresować moje pliki CSV do .gz przed przesłaniem do GCS za pomocą Cloud Function-Python 3.7, ale mój kod dodaje tylko rozszerzenie .gz, ale tak naprawdę nie kompresuje pliku, więc ostatecznie plik był uszkodzony. Czy możesz mi pokazać, jak to naprawić? Dzięki
Tutaj jest część mojego kodu
import gzip
def to_gcs(request):
job_config = bigquery.QueryJobConfig()
gcs_filename = 'filename_{}.csv'
bucket_name = 'bucket_gcs_name'
subfolder = 'subfolder_name'
client = bigquery.Client()
job_config.write_disposition = bigquery.WriteDisposition.WRITE_TRUNCATE
QUERY = "SELECT * FROM `bigquery-public-data.google_analytics_sample.ga_sessions_*` session, UNNEST(hits) AS hits"
query_job = client.query(
QUERY,
location='US',
job_config=job_config)
while not query_job.done():
time.sleep(1)
rows_df = query_job.result().to_dataframe()
storage_client = storage.Client()
storage_client.get_bucket(bucket_name).blob(subfolder+'/'+gcs_filename+'.gz').upload_from_string(rows_df.to_csv(sep='|',index=False,encoding='utf-8',compression='gzip'), content_type='application/octet-stream')
2 odpowiedzi
Zgodnie z sugestią w wątku, o którym mowa @Sam Mason w komentarzu, gdy już uzyskasz Datafame Pandas, powinieneś użyć TextIOWrapper()
i BytesIO()
, jak opisano w następującym przykładzie:
Poniższa próbka została zainspirowana odpowiedzią @ramhisera w ten wątek SO
df = query_job.result().to_dataframe()
blob = bucket.blob(f'{subfolder}/{gcs_filename}.gz')
with BytesIO() as gz_buffer:
with gzip.GzipFile(mode='w', fileobj=gz_buffer) as gz_file:
df.to_csv(TextIOWrapper(gz_file, 'utf8'), index=False)
blob.upload_from_file(gz_buffer,
content_type='application/octet-stream')
Zauważ również, że jeśli spodziewasz się, że ten plik będzie kiedykolwiek większy niż kilka MB, prawdopodobnie lepiej będzie użyć czegoś z moduł tempfile
zamiast BytesIO
. SpooledTemporaryFile
jest zasadniczo przeznaczony do tego przypadku użycia , gdzie użyje bufora pamięci do określonego rozmiaru i użyje dysku tylko wtedy, gdy plik stanie się naprawdę duży
ValueError: Stream must be at beginning
użyj wstaw gz_buffer.seek(0) przed linią blob.upload_from_file(...)
.
Cześć, próbowałem odtworzyć twój przypadek użycia:
Utworzyłem funkcję chmury za pomocą tego przewodnika szybkiego startu link:
def hello_world(request): from google.cloud import bigquery from google.cloud import storage import pandas as pd client = bigquery.Client() storage_client = storage.Client() path = '/tmp/file.gz' query_job = client.query(""" SELECT CONCAT( 'https://stackoverflow.com/questions/', CAST(id as STRING)) as url, view_count FROM `bigquery-public-data.stackoverflow.posts_questions` WHERE tags like '%google-bigquery%' ORDER BY view_count DESC LIMIT 10""") results = query_job.result().to_dataframe() results.to_csv(path,sep='|',index=False,encoding='utf-8',compression='gzip') bucket = storage_client.get_bucket('mybucket') blob = bucket.blob('file.gz') blob.upload_from_filename(path)
To jest
requirements.txt
:# Zależności funkcji, na przykład: google-cloud-bigquery Google Cloud Storage pandy
Wdrożyłem funkcję.
Sprawdziłem dane wyjściowe.
gsutil cp gs://mojzasobnik/plik.gz plik.gz gzip -d plik.gz plik kota #url|liczba_wyświetleń https://stackoverflow.com/questions/22879669|52306 https://stackoverflow.com/questions/13530967|46073 https://stackoverflow.com/questions/35159967|45991 https://stackoverflow.com/questions/10604135|45238 https://stackoverflow.com/questions/16609219|37758 https://stackoverflow.com/questions/11647201|32963 https://stackoverflow.com/questions/13221978|32507 https://stackoverflow.com/questions/27060396|31630 https://stackoverflow.com/questions/6607552|31487 https://stackoverflow.com/questions/11057219|29069
Podobne pytania
Powiązane pytania
Nowe pytania
python
Python to wielozadaniowy, wielozadaniowy język programowania dynamicznie typowany. Został zaprojektowany tak, aby był szybki do nauczenia się, zrozumienia i użycia oraz wymuszania czystej i jednolitej składni. Należy pamiętać, że Python 2 oficjalnie nie jest obsługiwany od 01-01-2020. Mimo to, w przypadku pytań Pythona specyficznych dla wersji, dodaj znacznik [python-2.7] lub [python-3.x]. Korzystając z wariantu Pythona (np. Jython, PyPy) lub biblioteki (np. Pandas i NumPy), należy umieścić go w tagach.
tempfile
. także metodaupload_from_string
natychmiast tworzy obiektBytesIO
, więc lepiej jest przekazać obiekt pliku, jeśli to możliwe, co jest teraz trywialne