Puncte:1

Când scrieți csv din CF în bucket: „cu deschis(filepath, „w”) ca MY_CSV:” duce la „FileNotFoundError: [Errno 2] Nu există un astfel de fișier sau director:”

drapel mx

Primesc această eroare FileNotFoundError: [Errno 2] Nu există un astfel de fișier sau director când încerc să scriu un fișier csv în găleată, folosind un scriitor csv care trece în buclă peste loturi de date. Informația completă a Funcției Cloud înregistrează această eroare:


Fișierul „/workspace/main.py”, linia 299, în write_to_csv_file with
open(filepath, "w") as outcsv: FileNotFoundError: [Errno 2] Nu există
fișier sau director: „gs://MY_BUCKET/MY_CSV.csv”

Execuția funcției a durat 52655 ms, s-a terminat cu starea: „crash” 

AVERTISMENT OpenBLAS - nu a putut determina dimensiunea cache-ului L2 pentru aceasta
sistem, presupunând 256k ```

Și asta, deși acest bucket_filepath există cu siguranță: pot încărca un fișier fals gol și pot obține „URI-ul gsutils” al acestuia (clic dreapta pe cele trei puncte din partea dreaptă a fișierului), iar bucket_filepath va arăta la fel: „gs://MY_BUCKET/MY_CSV.csv”.

Am verificat salvarea unui cadru de date panda fals în schimb folosind pd.to_csv și a funcționat cu același bucket_filepath (!).

Prin urmare, trebuie să existe un alt motiv, probabil că scriitorul nu este acceptat, sau cu declarație care deschide fișierul.

Codul care dă eroarea este următorul. Este cu același cod care funcționează în afara funcției Google Cloud într-o lucrare cron normală pe un server local. Am adăugat două imprimări de depanare în jurul liniei care aruncă eroarea, the print("Imediat dupa deschiderea fisierului...") nu mai apare. Subfuncția query_execute_batch() acea write_to_csv_file() apelează pentru fiecare lot este, de asemenea, afișat, dar probabil că nu este problema aici, deoarece eroarea se întâmplă deja chiar la început, când scrieți-deschideți fișierul csv.

cerințe.txt (care sunt apoi importate ca module):

SQLAlchemy>=1.4.2
google-cloud-storage>=1.16.1
mysqlclient==2.1.0
panda==1.2.3
fsspec==2021.11.1
gcsfs==2021.11.1
unicodecsv==0.14.1

Iar din principal.py:

def query_execute_batch(conexiune):
    """Funcția de citire a datelor din rezultatul interogării în loturi
    :yield: fiecare rezultat dintr-o buclă este un lot de rezultat al interogării
    """
    rezultate = execute_select_batch(conexiune, SQL_QUERY)
    print(f"len(rezultate): {len(rezultate)}")
    pentru rezultat în rezultate:
        randamentul rezultat

def write_to_csv_file(conexiune, cale fișier):
    """Scrieți datele într-o buclă peste loturi într-un csv.
    Acest lucru se face în loturi, deoarece interogarea din baza de date este uriașă.
    :param connection: mysqldb conexiune la DB
    :param filepath: calea către fișierul csv pentru a scrie date
    returnează: metadate pe rânduri și timp
    """
    countrows = 0
    print("Chiar inainte de a deschide fisierul...")    
    cu open(filepath, "w") ca outcsv:
        print("Imediat dupa deschiderea fisierului...")        
        scriitor = csv.DictWriter(
            outcsv,
            fieldnames=FIELDNAMES,
            extrasaction="ignora",
            delimitator="|",
            lineterminator="\n",
        )
        # scrie antetul în funcție de numele câmpurilor
        writer.writeheader()

        pentru lot în query_execute_batch(connection):
            writer.writerrows(lot)
            countrows += len(lot)
        datetime_now_save = datetime.now()
    returnează countrows, datetime_now_save

Rețineți că pentru ca scriptul de mai sus să funcționeze, import gcsfs ceea ce face găleata de citire-scriere-disponibilă. În caz contrar, probabil că aș avea nevoie de un obiect de stocare în cloud Google, cum ar fi, de exemplu:

storage_client = stocare.Client()
bucket = storage_client.bucket(BUCKET_NAME)

și apoi creați fișierul în acea găleată cu funcții suplimentare, dar acesta nu este scopul aici.

În cele ce urmează, pd.to_csv cod care funcționează, folosește rezultatul unei interogări SQL false SELECTARE 1 ca intrare a unui cadru de date. Acest poate sa să fie salvat în același bucket_filepath, desigur că motivul ar putea să nu fie doar pd.to_csv() ca atare, dar și că setul de date este un dummy în loc de șiruri unicode complexe dintr-un uriaș interogare SELECT. Sau există un alt motiv, doar bănuiesc.

dacă înregistrările nu sunt Niciunul:
    df = pd.DataFrame(records.fetchall())
    df.columns = records.keys()
    df.to_csv(filepath,
        index=fals,
    )
    datetime_now_save = datetime.now()
    countrows = df.shape[0]

Aș dori să folosesc scriitorul csv pentru a avea șansa de a scrie în unicode cu modulul unicodecsv și șansa de a folosi loturile.

S-ar putea să fiu dispus să schimb în loturi (buclă + anexă modul sau marimea bucatilor) în panda ca în Scrierea unor cadre mari de date Pandas în fișierul CSV în bucăți pentru a scăpa de această problemă a căii fișierelor din găleată, dar aș dori mai degrabă să folosesc codul gata (nu atingeți niciodată un sistem care rulează).

Cum pot realiza salvarea acelui csv cu scriitorul csv, astfel încât să poată deschide un fișier nou în găleată în scrie modul = cu open(filepath, "w") ca outcsv:?

Funcția dată write_to_csv_file() este doar o mică parte a funcției Cloud care utilizează o gamă largă de funcții și funcții în cascadă. Nu pot arăta aici întregul caz reproductibil și sper că se poate răspunde prin experiență sau exemple mai ușoare.

Puncte:1
drapel mx

Soluția este surprinzătoare. Tu trebuie sa importați și utilizați gcsfs modul dacă doriți să scrieți într-un fișier cu deschis().

Dacă utilizați pd.to_csv(), import gcsfs nu este necesar, dar gcsfs este încă nevoie în cerințe.txt a face pd.to_csv() muncă, astfel, panda to_csv() pare să-l folosească automat.

The pd.to_csv() surpriza lăsată deoparte, iată codul care răspunde la întrebare (testat):

def write_to_csv_file(conexiune, cale fișier):
    """Scrieți rezultatul QUERY într-o buclă peste loturi într-un csv.
    Acest lucru se face în loturi, deoarece interogarea din baza de date este uriașă.
    :param connection: mysqldb conexiune la DB
    :param filepath: calea către fișierul csv pentru a scrie date
    return: metadate pe rânduri și timp
    """
    countrows = 0
    print("Chiar inainte de a deschide fisierul...")
   

    # Un obiect gcsfs este necesar pentru a deschide un fișier.
    # https://stackoverflow.com/questions/52805016/how-to-open-a-file-from-google-cloud-storage-into-a-cloud-function
    # https://gcsfs.readthedocs.io/en/latest/index.html#examples
    # Notă secundară (excepție):
    # pd.to_csv() nu are nevoie nici de obiectul gcsfs, nici de importul acestuia.
    # Nu este folosit aici, dar a fost testat cu exemple.
    fs = gcsfs.GCSFileSystem(project=MY_PROJECT)
    fs.ls(BUCKET_NAME)


    # wb este necesar, altfel „builtins.TypeError: trebuie să fie str, nu octeți”
    # https://stackoverflow.com/questions/5512811/builtins-typeerror-must-be-str-not-bytes
    cu fs.open(filepath, 'wb') ca outcsv:
        print("Imediat dupa deschiderea fisierului...")

        scriitor = csv.DictWriter(
            outcsv,
            fieldnames=FIELDNAMES,
            extrasaction="ignora",
            delimitator="|",
            lineterminator="\n",
        )
        # scrie antetul în funcție de numele câmpurilor
        print("inainte de writer.writeheader()")
        writer.writeheader()
        print("dupa writer.writeheader()")

        pentru lot în query_execute_batch(connection):
            writer.writerrows(lot)
            countrows += len(lot)
        datetime_now_save = datetime.now()
    returnează countrows, datetime_now_save

Notă marginală

Nu utilizați scriitorul csv așa.

Durează prea mult, în loc de pd.to_csv() cu marimea bucatilor parametrul 5000, care are nevoie de doar 62 de secunde pentru ca rândurile de 700.000 să fie încărcate și stocate ca csv în găleată, CF cu scriitorul de loturi durează mai mult de cele 9 minute care depășesc limita de timeout. eu sunt prin urmare forțat să folosească pd.to_csv() în schimb și îmi convertesc datele într-un cadru de date pentru asta.

Postează un răspuns

Majoritatea oamenilor nu înțeleg că a pune multe întrebări deblochează învățarea și îmbunătățește legătura interpersonală. În studiile lui Alison, de exemplu, deși oamenii își puteau aminti cu exactitate câte întrebări au fost puse în conversațiile lor, ei nu au intuit legătura dintre întrebări și apreciere. În patru studii, în care participanții au fost implicați în conversații ei înșiși sau au citit transcrieri ale conversațiilor altora, oamenii au avut tendința să nu realizeze că întrebarea ar influența – sau ar fi influențat – nivelul de prietenie dintre conversatori.