python - 从云函数在 Google Cloud Storage 中创建新的 csv 文件

标签 python csv google-cloud-platform google-cloud-functions google-cloud-storage

第一次使用 Google Cloud Storage。下面我有一个云函数,每当 csv 文件上传到我的存储桶内的 my-folder 时就会触发该函数。我的目标是在同一文件夹中创建一个新的 csv 文件,读取上传的 csv 的内容并将每一行转换为将进入新创建的 csv 的 URL。问题是我在创建新 csv 时就遇到了麻烦,更不用说实际写入它了。

我的代码:

import os.path
import csv
import sys
import json
from csv import reader, DictReader, DictWriter
from google.cloud import storage
from io import StringIO

def generate_urls(data, context):
    if context.event_type == 'google.storage.object.finalize':
        storage_client = storage.Client()
        bucket_name = data['bucket']
        bucket = storage_client.get_bucket(bucket_name)
        folder_name = 'my-folder'
        file_name = data['name']

        if not file_name.endswith('.csv'):
            return

接下来的几行来自 an example在 GCP 的 GitHub 存储库中。这是我期望创建新的 csv 的时候,但什么也没有发生。

        # Prepend 'URL_' to the uploaded file name for the name of the new csv
        destination = bucket.blob(bucket_name + '/' + file_name[:14] + 'URL_' + file_name[14:])
        destination.content_type = 'text/csv'
        sources = [bucket.get_blob(file_name)]
        destination.compose(sources)
        output = bucket_name + '/' + file_name[:14] + 'URL_' + file_name[14:]


        # Transform uploaded csv to string - this was recommended on a similar SO post, not sure if this works or is the right approach...
        blob = bucket.blob(file_name)
        blob = blob.download_as_string()
        blob = blob.decode('utf-8')
        blob = StringIO(blob)

        input_csv = csv.reader(blob)

下一行是我收到错误的地方:没有这样的文件或目录:'myProjectId/my-folder/URL_my_file.csv'

        with open(output, 'w') as output_csv:
            csv_dict_reader = csv.DictReader(input_csv, )
            csv_writer = csv.DictWriter(output_csv, fieldnames=['URL'], delimiter=',', quotechar='"', quoting=csv.QUOTE_ALL)
            csv_writer.writeheader()
            line_count = 0
            for row in csv_dict_reader:
                line_count += 1
                url = ''
                ...
                # code that converts each line
                ...
                csv_writer.writerow({'URL': url})
            print(f'Total rows: {line_count}')

如果有人对我如何创建新的 csv 然后写入它有任何建议,这将是一个巨大的帮助。谢谢!

最佳答案

我可能会说我对代码和解决方案的设计有一些疑问:

  1. 据我了解 - 一方面,云函数是由 finalise 事件触发的 Google Cloud Storage Triggers ,而不是另一方面,您想将新创建的文件保存到同一个存储桶中。成功后,该存储桶中出现新对象将触发云函数的另一个实例。这是预期的行为吗?您的云功能准备好了吗?

  2. 从本体论上来说,不存在文件夹这样的东西。因此在这段代码中:

        folder_name = 'my-folder'
        file_name = data['name']

第一行有点多余,除非您想将该变量和值用于其他用途...并且 file_name 获取包括所有前缀的对象名称(您可以将它们视为“文件夹”。

  • 您引用的示例 - storage_compose_file.py - 是关于如何将 GCS 中的几个对象组合成一个。我不确定该示例是否与您的情况相关,除非您有一些其他要求。

  • 现在,让我们看一下这段代码:

  •         destination = bucket.blob(bucket_name + '/' + file_name[:14] + 'URL_' + file_name[14:])
            destination.content_type = 'text/csv'
            sources = [bucket.get_blob(file_name)]
            destination.compose(sources)
    

    a. bucket.blob - 是一个工厂构造函数 - 请参阅 API buckets description 。我不确定您是否真的想使用 bucket_name 作为其参数的元素...

    b. sources - 成为仅包含一个元素的列表 - 对 GCS 存储桶中现有对象的引用。

    c. destination.compose(sources) - 是否尝试复制现有对象?如果成功 - 它可能会触发您的云函数的另一个实例。

  • 关于类型更改
  •         blob = bucket.blob(file_name)
            blob = blob.download_as_string()
    

    第一行之后,blob 变量的类型为 google.cloud.storage.blob.Blob。在第二个 - 字节之后。我认为 Python 允许这样的事情......但你真的喜欢它吗?顺便说一句,download_as_string 方法已弃用 - 请参阅 Blobs / Objects API

  • 关于输出:
  •    output = bucket_name + '/' + file_name[:14] + 'URL_' + file_name[14:]
        
       with open(output, 'w') as output_csv:
    

    请记住 - 所有这些都发生在云函数的内存中。与 GCS 的 blob 桶无关。如果您想在云函数中使用临时文件 - 您将在 /tmp 目录中使用它们 - Write temporary files from Google Cloud Function我猜您会因为这个问题而收到错误。

    => 提出一些建议。

    您可能希望将对象下载到云函数内存中(下载到 /tmp 目录中)。然后您想处理源文件并将结果保存在源附近。然后您想将结果上传到另一个(不是源)存储桶。如果我的假设是正确的,我建议一步一步地实现这些事情,并检查每一步是否得到了预期的结果。

    关于python - 从云函数在 Google Cloud Storage 中创建新的 csv 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69399970/

    相关文章:

    python - 如何在python中测量算法的运行时间

    python - 将 Pandas 数据框转换为所需的 python 字典

    google-app-engine - GCP 将自定义域指向特定的 App Engine 服务

    python - 有没有一种有意义的方法可以在生成器中使用上下文管理器?

    python - 当我在 Python 中使用 stdout 时,为什么 Powershell 无法显示字符串?

    PHP 插入 - 首次输入的 UID 较大

    python - UnicodeDecodeError 读取 CSV 中的字符串

    python - Apache NiFi : Processing multiple csv's using the ExecuteScript Processor

    google-cloud-platform - GCP : Identify correct instance(N1standard 8, N1Highmem 等)使用目录 API

    java - 如何禁用DEBUG日志