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.