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')

0
Justine 16 grudzień 2019, 15:55
1
 – 
Sam Mason
16 grudzień 2019, 16:49
Sprawdź ostrzeżenia, które otrzymujesz od Pand, zobacz stackoverflow.com/a/44168817/1358308 i github.com/pandas-dev/pandas/issues/22555
 – 
Sam Mason
16 grudzień 2019, 16:50
Najczęściej głosowana odpowiedź z pierwszego komentarza @SamMason zadziałała dla mnie. Czy to zadziałało dla Ciebie @Justine?
 – 
Jose V
17 grudzień 2019, 13:18
V, tak!
 – 
Justine
18 grudzień 2019, 18:33
1
Miałem skrzypce i dodałem notatkę o korzystaniu z modułu tempfile. także metoda upload_from_string natychmiast tworzy obiekt BytesIO, więc lepiej jest przekazać obiekt pliku, jeśli to możliwe, co jest teraz trywialne
 – 
Sam Mason
19 grudzień 2019, 17:50

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

3
2 revs, 2 users 73% 19 grudzień 2019, 17:48
Dla osób mających do czynienia z ValueError: Stream must be at beginning użyj wstaw gz_buffer.seek(0) przed linią blob.upload_from_file(...).
 – 
Yoyo
9 lipiec 2021, 10:46

Cześć, próbowałem odtworzyć twój przypadek użycia:

  1. 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)
    
    1. To jest requirements.txt:

      # Zależności funkcji, na przykład:   google-cloud-bigquery  Google Cloud Storage  pandy  
    2. Wdrożyłem funkcję.

    3. 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  
0
marian.vladoi 17 grudzień 2019, 15:01