【问题标题】:Write a CSV to store in Google Cloud Storage写入 CSV 以存储在 Google Cloud Storage 中
【发布时间】:2017-01-24 06:36:11
【问题描述】:

背景:我正在我的 Python/AppEngine 项目中获取数据并创建一个 .tsv 文件,以便我可以使用 d3.js 创建图表。现在我正在为每个页面加载编写 CSV;我想将文件存储在 Google Cloud Storage 中一次并从那里读取。

每次加载页面时,我当前如何编写文件!:

def get(self):  ## this gets called when loading myfile.tsv from d3.js
    datalist = MyEntity.all()
    self.response.headers['Content-Type'] = 'text/csv'
    writer = csv.writer(self.response.out, delimiter='\t')
    writer.writerow(['field1', 'field2'])
    for eachco in datalist:
        writer.writerow([eachco.variable1, eachco.variable2])

虽然效率低,但效果很好。

使用this Google Cloud Storage documentation,我一直在尝试让这样的工作:

def get(self):
    filename = '/bucket/myfile.tsv'
    datalist = MyEntity.all()
    bucket_name = os.environ.get('BUCKET_NAME', app_identity.get_default_gcs_bucket_name())
    write_retry_params = gcs.RetryParams(backoff_factor=1.1)
    writer = csv.writer(self.response.out, delimiter='\t')
    gcs_file = gcs.open(filename, 'w', content_type='text/csv', retry_params=write_retry_params)
    gcs_file.write(writer.writerow(['field1', 'field2']))
    for eachco in datalist:
        gcs_file.write(writer.writerow([eachco.variable1, eachco.variable2]))
    gcs_file.close()

但我得到了:

TypeError: Expected str but got <type 'NoneType'>.

我认为 csv.writer 的输出会是一个字符串,所以我不确定为什么会收到 TypeError。

所以我可以想到两种情况:

  1. 我的代码中有一些东西搞砸了,将 tsv 写入 云储存。不过,遍历并将 TSV/CSV 文件写入 Cloud Storage 应该很简单,对吧?
  2. 我的做法完全错误 完全,甚至应该使用 BlobStore 或 db.TextProperty() 存储此 .tsv 数据。 (文件不是那么大;绝对 远低于 1MB)

如果有任何帮助,我将不胜感激!

编辑 - 完整追溯

Traceback (most recent call last):
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2-2.5.1/webapp2.py", line 1530, in __call__
    rv = self.router.dispatch(request, response)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2-2.5.1/webapp2.py", line 1278, in default_dispatcher
    return route.handler_adapter(request, response)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2-2.5.1/webapp2.py", line 1102, in __call__
    return handler.dispatch()
  File "/mydirectory/myapp/handlers.py", line 21, in dispatch
    webapp2.RequestHandler.dispatch(self)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2-2.5.1/webapp2.py", line 572, in dispatch
    return self.handle_exception(e, self.app.debug)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2-2.5.1/webapp2.py", line 570, in dispatch
    return method(*args, **kwargs)
  File "/mydirectory/myapp/thisapp.py", line 384, in get
    gcs_file.write(writer.writerow(['field1', 'field2']))
  File "lib/cloudstorage/storage_api.py", line 754, in write
    raise TypeError('Expected str but got %s.' % type(data))
TypeError: Expected str but got <type 'NoneType'>.

【问题讨论】:

  • 你忘记设置响应头了。
  • 可以添加完整的回溯吗?
  • 我不知道你想用这个gcs_file.write(str(writer.writerow([eachco.variable1, eachco.variable2]))) 线实现什么。
  • 噢!我也试过: gcs_file.write(writer.writerow([eachco.variable1, eachco.variable2])) 但它没有用。我将编辑上面的代码。
  • Dan - 在上面添加了完整的回溯 // Avinash - 我相信响应标头是通过以下方式设置的:gcs_file = gcs.open(filename, 'w', content_type='text/csv', retry_params =write_retry_params)

标签: python csv google-app-engine google-cloud-storage


【解决方案1】:

您仍在尝试在响应中创建作者:

writer = csv.writer(self.response.out, delimiter='\t')

您需要写入 GCS 文件。像这样的:

    datalist = MyEntity.all()
    bucket_name = os.environ.get('BUCKET_NAME', app_identity.get_default_gcs_bucket_name())
    filename = os.path.join(bucket_name, 'myfile.tsv')
    write_retry_params = gcs.RetryParams(backoff_factor=1.1)
    gcs_file = gcs.open(filename, 'w', content_type='text/csv', retry_params=write_retry_params)
    writer = csv.writer(gcs_file, delimiter='\t')
    writer.writerow(['field1', 'field2'])
    for eachco in datalist:
        writer.writerow([eachco.variable1, eachco.variable2])
    gcs_file.close()

注意事项:

  • 未经实际测试
  • 我还调整了文件名以使用bucket_name
  • 如果您在get() 请求中执行此操作,您可能需要检查该文件是否已经存在,如果存在,请使用它,否则您仍然会在每次请求时生成它。或者,您可以将此代码移动到任务上或 .tsv 上传处理程序中。

【讨论】:

  • 行得通!我仍然必须使用 filename = '/bucket/myfile.tsv' 行,因为这是 GCS 明确要求的格式。 (错误是 ValueError: Path should have format /bucket/filename but got app_default_bucket/myfile.tsv)
  • 啊,我怀疑缺少前导“/”。请改用filename = '/%s/myfile.tsv' % bucket_name(假设默认应用存储桶的名称在生产环境中为bucket 可能不是一个好主意)。
【解决方案2】:

问题是writer.writerow 没有返回任何东西。返回类型将为None,而您正尝试将其写入gcs_file

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-05-05
    • 2022-07-25
    • 2019-02-14
    • 1970-01-01
    • 2021-04-18
    • 2023-03-13
    • 2018-11-17
    • 1970-01-01
    相关资源
    最近更新 更多