【问题标题】:Implementing a cloud function to publish to pubsub triggered by GCS finalize实现由 GCS finalize 触发的云功能以发布到 pubsub
【发布时间】:2018-12-06 05:57:01
【问题描述】:

我一直在尝试用 Python 编写和部署云函数。 (由于文档凌乱且更改速度相对较快,放弃了 node.js)

这意味着向 Pub/Sub 主题发布消息,当文件完成上传到谷歌云存储桶时触发(“finalize”)。

我用来部署功能的代码是

gcloud functions deploy hello_gcs_generic --runtime python37 --trigger-resource bucketcfpubsub

我一直在尝试使用this script provided by Google

import time

from google.cloud import pubsub_v1

project_id = "bucketcfpubsub"
topic_name = "projects/bucketcfpubsub/topics/pubsub"

publisher = pubsub_v1.PublisherClient()
topic_path = publisher.topic_path(project_id, topic_name)

def callback(message_future):
# When timeout is unspecified, the exception method waits indefinitely.
if message_future.exception(timeout=30):
    print('Publishing message on {} threw an Exception {}.'.format(
        topic_name, message_future.exception()))
else:
    print(message_future.result())

for n in range(1, 10):
    data = u'Message number {}'.format(n)
# Data must be a bytestring
    data = data.encode('utf-8')
# When you publish a message, the client returns a Future.
    message_future = publisher.publish(topic_path, data=data)
    message_future.add_done_callback(callback)

print('Published message IDs:')

# We must keep the main thread from exiting to allow it to process
# messages in the background.
while True:
    time.sleep(60)

我在 Google Cloud Console 中收到这些错误

ERROR: (gcloud.functions.deploy) OperationError: code=3, message=Function load error: Code in file main.py can't be loaded.
Detailed stack trace: Traceback (most recent call last):
  File "/env/local/lib/python3.7/site-packages/google/cloud/functions_v1beta2/worker.py", line 256, in check_or_load_user_function
    _function_handler.load_user_function()
  File "/env/local/lib/python3.7/site-packages/google/cloud/functions_v1beta2/worker.py", line 166, in load_user_function
    spec.loader.exec_module(main)
  File "<frozen importlib._bootstrap_external>", line 728, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "<frozen importlib._bootstrap_external>", line 728, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "/user_code/main.py", line 3, in <module>
    from google.cloud import pubsub_v1
ImportError: cannot import name 'pubsub_v1' from 'google.cloud' (unknown location)

按照 these two 帖子的说明,我从 helloworld 代码示例中复制了 requirements.txt,其中仅包含

google-cloud-error-reporting==0.30.0

并更新了其他云功能,例如 bigquery、存储和日志记录。然后我得到了这些错误:

ERROR: (gcloud.functions.deploy) OperationError: code=3, message=Function load error: Code in file main.py can't be loaded.
Detailed stack trace: Traceback (most recent call last):
  File "/env/local/lib/python3.7/site-packages/google/cloud/functions_v1beta2/worker.py", line 256, in check_or_load_user_function
    _function_handler.load_user_function()
  File "/env/local/lib/python3.7/site-packages/google/cloud/functions_v1beta2/worker.py", line 166, in load_user_function
    spec.loader.exec_module(main)
  File "<frozen importlib._bootstrap_external>", line 728, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "/user_code/main.py", line 3, in <module>
from google.cloud import pubsub_v1`

我还找到了 [this thread](ImportError: cannot import name 'pubsub_v1' from 'google.cloud' (unknown location),但我不太明白解决方案是什么,我尝试用 google-cloud-pubsub==0.38.0 替换 pubsub_v1,但没有帮助。我明白了而是这个错误:

Deploying function (may take a while - up to 2 minutes)...failed.
ERROR: (gcloud.functions.deploy) OperationError: code=3, message=Function load error: Code in file main.py can't be loaded.
Detailed stack trace: Traceback (most recent call last):
  File "/env/local/lib/python3.7/site-packages/google/cloud/functions_v1beta2/worker.py", line 256, in check_or_load_user_function
    _function_handler.load_user_function()
  File "/env/local/lib/python3.7/site-packages/google/cloud/functions_v1beta2/worker.py", line 166, in load_user_function
    spec.loader.exec_module(main)
  File "<frozen importlib._bootstrap_external>", line 724, in exec_module
  File "<frozen importlib._bootstrap_external>", line 860, in get_code
  File "<frozen importlib._bootstrap_external>", line 791, in source_to_code
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "/user_code/main.py", line 3

此外,如果 Google 将 pubsub 更新到新版本后代码会中断,这似乎不是一个可持续的解决方案?

所以我是一个初学者并且很迷茫,但我希望这个文档可以帮助你们帮助我。

更新:

似乎 pubsub 和 pubsub_v1 都可以使用,但不确定有什么区别。

@dustin 我做了一个 pip install -r requirements.txt 最终匹配你提供的内容。 我还注意到将函数部署为“hello-gcs-generic”时出错,应将其更改为“回调”。

python 代码现在在本地运行良好,但使用上述代码(OP 中的第一行代码)将其部署到云端时始终返回此错误

ERROR: (gcloud.functions.deploy) OperationError: code=3, messa
ge=Function load error: Error: function load attempt timed out
.

【问题讨论】:

  • 节点文档有什么乱七八糟的?哪些 API 更改存在问题?
  • 作为一个完整的初学者,我得到了从 0.xx 到 8.xx 的教程和代码 sn-ps,其中很少有被标记的。遇到一些似乎在某处破坏了兼容性的语法和对象,并感到困惑。 IIRC 有一个关于 from.events 和缓冲区的问题,但我没有记录这些问题,所以无法解释更多,抱歉。
  • 我在 Cloud Functions、桌面、服务器等中使用 Pub/Sub。遗漏了一些掩盖您真正问题的东西。 1) 不要为 Google Cloud 客户端库指定版本号。除非您有技术原因,否则请使用最新版本。 2)编辑您的问题并包含您的所有代码。 3) 包括您的 requirements.txt。 4) Python 源代码格式对于理解代码至关重要。通过使用正确的缩进正确格式化 Python 源代码来更新您的问题。 5) 包含您在 Cloud Function 部署中包含的文件的布局。
  • 尝试运行前面带 sudo 的代码。

标签: python google-cloud-platform google-cloud-storage google-cloud-functions google-cloud-pubsub


【解决方案1】:

您需要将google-cloud-pubsub 添加到您的requirements.txt 文件中,而不是添加到您的main.py 文件中。它应该是这样的:

google-cloud-error-reporting==0.30.0
google-cloud-pubsub==0.38.0

【讨论】:

  • 抱歉,我似乎无法让 @ 函数在 SO 中工作。请参阅 OP 底部以获取更新。
  • @LarryCai 您的函数可能由于while True: time.sleep(60) 而超时,您为什么需要它?
  • @LarryCai 我现在看到这是来自示例 here,您可以尝试同步等待每个未来的 result() 调用而不是休眠。
【解决方案2】:

simpler Python quickstart example 可以满足您的需求。 ;-)

您引用的示例更高级。它展示了如何发布带有错误处理的消息。高级示例中的while(True): sleep(60) 行用于保持主线程处于活动状态,除非发出Ctrl+C 或其等效项来阻止程序运行。这个sleep 函数存在的原因是我们可以等待发布期货上的回调调用完成,而不是在发布调用后立即退出程序。同样,对于您尝试学习使用 Cloud Pub/Sub 和 Cloud Functions 进行的操作而言,这可能有点过于复杂。我建议不要使用高级示例并使用快速入门示例。

from google.cloud import pubsub_v1

# TODO project_id = "Your Google Cloud Project ID"
# TODO topic_name = "Your Pub/Sub topic name"

publisher = pubsub_v1.PublisherClient()
# The `topic_path` method creates a fully qualified identifier
# in the form `projects/{project_id}/topics/{topic_name}`
topic_path = publisher.topic_path(project_id, topic_name)

for n in range(1, 10):
    data = u'Message number {}'.format(n)
    # Data must be a bytestring
    data = data.encode('utf-8')
    # When you publish a message, the client returns a future.
    future = publisher.publish(topic_path, data=data)
    print('Published {} of message ID {}.'.format(data, future.result()))

print('Published messages.')

【讨论】:

    猜你喜欢
    • 2020-11-26
    • 2020-02-06
    • 2021-10-31
    • 2020-08-30
    • 1970-01-01
    • 1970-01-01
    • 2021-07-04
    • 2021-09-19
    • 2020-12-10
    相关资源
    最近更新 更多