AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / server / Perguntas / 1091789
Accepted
questionto42standswithUkraine
questionto42standswithUkraine
Asked: 2022-02-01 09:32:39 +0800 CST2022-02-01 09:32:39 +0800 CST 2022-02-01 09:32:39 +0800 CST

Ao escrever csv do CF para o bucket: 'with open(filepath, "w") as MY_CSV:' leva a "FileNotFoundError: [Errno 2] No such file or directory:"

  • 772

Recebo esse erro FileNotFoundError: [Errno 2] No such file or directoryquando tento gravar um arquivo csv no bucket, usando um gravador csv que faz um loop em lotes de dados. O insight completo sobre os registros do Cloud Function em torno desse erro:


File "/workspace/main.py", line 299, in write_to_csv_file with
open(filepath, "w") as outcsv: FileNotFoundError: [Errno 2] No such
file or directory: 'gs://MY_BUCKET/MY_CSV.csv'

Function execution took 52655 ms, finished with status: 'crash' 

OpenBLAS WARNING - could not determine the L2 cache size on this
system, assuming 256k  ```

E isso, embora este bucket_filepath definitivamente exista: posso fazer upload de um arquivo fictício vazio e obter seu "gsutils URI" (clique com o botão direito do mouse nos três pontos no lado direito do arquivo) e o bucket_filepath terá a mesma aparência: 'gs://MY_BUCKET/MY_CSV.csv'.

Eu verifiquei salvar um dataframe de pandas fictício usando pd.to_csve funcionou com o mesmo bucket_filepath (!).

Portanto, deve haver outro motivo, provavelmente o gravador não é aceito, ou o with statementque abre o arquivo.

O código que gera o erro é o seguinte. É com o mesmo código trabalhando fora do Google Cloud Function em um cron job normal em um servidor local. Eu adicionei duas impressões de depuração ao redor da linha que lança o erro, o print("Right after opening the file ...")que não aparece mais. A subfunção query_execute_batch()que write_to_csv_file()está chamando para cada lote também é mostrada, mas provavelmente não é o problema aqui, pois o erro já ocorre no início ao abrir o arquivo csv.

requirements.txt(que são então importados como módulos):

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

E a partir de main.py:

def query_execute_batch(connection):
    """Function for reading data from the query result into batches
    :yield: each result in a loop is a batch of the query result
    """
    results = execute_select_batch(connection, SQL_QUERY)
    print(f"len(results): {len(results)}")
    for result in results:
        yield result

def write_to_csv_file(connection, filepath):
    """Write the data in a loop over batches into a csv.
    This is done in batches since the query from the database is huge.
    :param connection: mysqldb connection to DB
    :param filepath: path to csv file to write data
    returns: metadata on rows and time
    """
    countrows = 0
    print("Right before opening the file ...")    
    with open(filepath, "w") as outcsv:
        print("Right after opening the file ...")        
        writer = csv.DictWriter(
            outcsv,
            fieldnames=FIELDNAMES,
            extrasaction="ignore",
            delimiter="|",
            lineterminator="\n",
        )
        # write header according to fieldnames
        writer.writeheader()

        for batch in query_execute_batch(connection):
            writer.writerows(batch)
            countrows += len(batch)
        datetime_now_save = datetime.now()
    return countrows, datetime_now_save

Lembre-se de que, para que o script acima funcione, eu importo, gcsfso que torna o bucket disponível para leitura e gravação. Caso contrário, eu provavelmente precisaria de um objeto de armazenamento em nuvem do Google, como por exemplo:

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

e, em seguida, faça o arquivo nesse bucket com outras funções, mas esse não é o objetivo aqui.

A seguir, o pd.to_csvcódigo que funciona, ele usa a saída de uma consulta SQL fictícia SELECT 1como entrada de um dataframe. Isso pode ser salvo no mesmo bucket_filepath, é claro que o motivo pode não ser apenas pd.to_csv()como tal, mas também que o conjunto de dados é um manequim em vez de strings unicode complexas de um enorme arquivo SELECT query. Ou há outra razão, estou apenas supondo.

if records is not None:
    df = pd.DataFrame(records.fetchall())
    df.columns = records.keys()
    df.to_csv(filepath,
        index=False,
    )
    datetime_now_save = datetime.now()
    countrows = df.shape[0]

Eu gostaria de usar o gravador csv para ter a chance de escrever em unicode com o módulo unicodecsv e a chance de usar os lotes.

Eu posso estar disposto a mudar para lotes ( loop + appendmode ou chunksize) em pandas como em Escrevendo dataframes grandes de Pandas para arquivo CSV em pedaços para se livrar desse problema de caminho de arquivo do bucket, mas eu gostaria de usar o código pronto (nunca toque em um sistema em execução ).

Como posso salvar esse csv com o gravador csv para que ele possa abrir um novo arquivo no bucket em writemode = with open(filepath, "w") as outcsv:?

A função fornecida write_to_csv_file()é apenas uma pequena parte da Cloud Function que usa uma ampla variedade de funções e funções em cascata. Não posso mostrar todo o caso reproduzível aqui e espero que possa ser respondido pela experiência ou por exemplos mais fáceis.

filesystems google-cloud-platform google-cloud-functions
  • 1 1 respostas
  • 910 Views

1 respostas

  • Voted
  1. Best Answer
    questionto42standswithUkraine
    2022-02-01T13:05:37+08:002022-02-01T13:05:37+08:00

    A solução é surpreendente. Você deve importar e usar o gcsfsmódulo se quiser gravar em um arquivo com extensão open().

    Se você usa pd.to_csv(), import gcsfsnão é necessário, mas gcsfsainda é necessário requirements.txtpara fazer pd.to_csv()funcionar , assim, os pandas to_csv()parecem usá-lo automaticamente.

    Deixando a pd.to_csv()surpresa de lado, aqui está o código que responde à pergunta (testado):

    def write_to_csv_file(connection, filepath):
        """Write the QUERY result in a loop over batches into a csv.
        This is done in batches since the query from the database is huge.
        :param connection: mysqldb connection to DB
        :param filepath: path to csv file to write data
        return: metadata on rows and time
        """
        countrows = 0
        print("Right before opening the file ...")
       
    
        # A gcsfs object is needed to open a file.
        # 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
        # Side-note (Exception):
        # pd.to_csv() needs neither the gcsfs object, nor its import.
        # It is not used here, but it has been tested with examples.
        fs = gcsfs.GCSFileSystem(project=MY_PROJECT)
        fs.ls(BUCKET_NAME)
    
    
        # wb needed, else "builtins.TypeError: must be str, not bytes"
        # https://stackoverflow.com/questions/5512811/builtins-typeerror-must-be-str-not-bytes
        with fs.open(filepath, 'wb') as outcsv:
            print("Right after opening the file ...")
    
            writer = csv.DictWriter(
                outcsv,
                fieldnames=FIELDNAMES,
                extrasaction="ignore",
                delimiter="|",
                lineterminator="\n",
            )
            # write header according to fieldnames
            print("before writer.writeheader()")
            writer.writeheader()
            print("after writer.writeheader()")
    
            for batch in query_execute_batch(connection):
                writer.writerows(batch)
                countrows += len(batch)
            datetime_now_save = datetime.now()
        return countrows, datetime_now_save
    

    Nota

    Não use o gravador csv assim.

    Demora muito, em vez do pd.to_csv()com chunksizeparâmetro de 5000 que precisa de apenas 62s para que as 700k linhas sejam carregadas e armazenadas como um csv no bucket, o CF com o gravador de lotes demora mais do que os 9 minutos que são sobre o limite de tempo limite. Portanto, sou forçado a usar pd.to_csv()e converter meus dados em um dataframe para isso.

    • 1

relate perguntas

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Você pode passar usuário/passar para autenticação básica HTTP em parâmetros de URL?

    • 5 respostas
  • Marko Smith

    Ping uma porta específica

    • 18 respostas
  • Marko Smith

    Verifique se a porta está aberta ou fechada em um servidor Linux?

    • 7 respostas
  • Marko Smith

    Como automatizar o login SSH com senha?

    • 10 respostas
  • Marko Smith

    Como posso dizer ao Git para Windows onde encontrar minha chave RSA privada?

    • 30 respostas
  • Marko Smith

    Qual é o nome de usuário/senha de superusuário padrão para postgres após uma nova instalação?

    • 5 respostas
  • Marko Smith

    Qual porta o SFTP usa?

    • 6 respostas
  • Marko Smith

    Linha de comando para listar usuários em um grupo do Windows Active Directory?

    • 9 respostas
  • Marko Smith

    O que é um arquivo Pem e como ele difere de outros formatos de arquivo de chave gerada pelo OpenSSL?

    • 3 respostas
  • Marko Smith

    Como determinar se uma variável bash está vazia?

    • 15 respostas
  • Martin Hope
    Davie Ping uma porta específica 2009-10-09 01:57:50 +0800 CST
  • Martin Hope
    kernel O scp pode copiar diretórios recursivamente? 2011-04-29 20:24:45 +0800 CST
  • Martin Hope
    Robert ssh retorna "Proprietário incorreto ou permissões em ~/.ssh/config" 2011-03-30 10:15:48 +0800 CST
  • Martin Hope
    Eonil Como automatizar o login SSH com senha? 2011-03-02 03:07:12 +0800 CST
  • Martin Hope
    gunwin Como lidar com um servidor comprometido? 2011-01-03 13:31:27 +0800 CST
  • Martin Hope
    Tom Feiner Como posso classificar a saída du -h por tamanho 2009-02-26 05:42:42 +0800 CST
  • Martin Hope
    Noah Goodrich O que é um arquivo Pem e como ele difere de outros formatos de arquivo de chave gerada pelo OpenSSL? 2009-05-19 18:24:42 +0800 CST
  • Martin Hope
    Brent Como determinar se uma variável bash está vazia? 2009-05-13 09:54:48 +0800 CST

Hot tag

linux nginx windows networking ubuntu domain-name-system amazon-web-services active-directory apache-2.4 ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve