在 Google Cloud 函数中访问用户定义的包(ModuleNotFoundError: No module named...)

Posted

技术标签:

【中文标题】在 Google Cloud 函数中访问用户定义的包(ModuleNotFoundError: No module named...)【英文标题】:Accessing User-Defined Packages in Google Cloud Function (ModuleNotFoundError: No module named...) 【发布时间】:2019-03-02 13:45:29 【问题描述】:

我正在从源代码库部署 Google Cloud 功能。只要我没有在我的main.py 中对存储库中的任何用户定义函数(即以下packagepackage2 中的脚本/函数)进行任何引用,我就可以很好地部署Google 函数除了main.py)。

.
├── package
|   ├── __init__.py
|   ├── main.py
|   ├── requirements.txt
|   ├── script1.py
|   └── script2.py
├── package2
|   ├── __init__.py
|   ├── script3.py
|   └── script4.py
└── ...

我最近有 2 个关于此功能部署 here 和 here 的 Stack Overflow 问题。他们共同指导我找到了一个解决方案,其中main.pyrequirements.txt 在一个包中,我以该包作为源部署了谷歌云功能。现在的问题是我需要能够访问其他包/脚本中的函数/脚本。如果我在 main.py 中包含类似 from package.script1 import foo 的语句,我在部署函数时会收到如下错误:

ERROR: (gcloud.functions.deploy) OperationError: code=3, message=Function load error: Code in file main.py can't be loaded.
Did you list all required modules in requirements.txt?
Detailed stack trace: Traceback (most recent call last):
  File "/env/local/lib/python3.7/site-packages/google/cloud/functions_v1beta2/wo
rker.py", line 211, in check_or_load_user_function
    _function_handler.load_user_function()
  File "/env/local/lib/python3.7/site-packages/google/cloud/functions_v1beta2/wo
rker.py", line 140, 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 4, in <module>
    from package.script1 import foo
ModuleNotFoundError: No module named 'package'

我目前正在使用这个谷歌函数部署语句部署这个函数:

gcloud functions deploy NAME --source https://source.developers.google.com/projects/PROJECT_ID/repos/REPOSITORY_ID/moveable-aliases/BRANCH_NAME/paths/package/ --trigger-topic TOPIC

由于this stack overflow question 中的问题,无法将main.pyrequirements.txt 移回根目录。

我需要一种在gcloud functions deploy ... 语句期间导入用户定义的包/函数的方法。我的main.py 使用了package.script1.pypackage.script2.pypackage2.script3.pypackage2.script4.py 中的函数。这如何实现?

编辑/更新信息

我在每个包(packagepackage2)中都有 __init__.py 文件,但它们目前是空白/空的。

我尝试了以下gcloud deploy... 选项:

    main.pyrequirements.txt 在根目录中(而不是如上/最初所示的配置)使用此部署命令:

    gcloud functions deploy NAME --source https://source.developers.google.com/projects/PROJECT_ID/repos/REPOSITORY_ID/moveable-aliases/BRANCH --trigger-topic TOPIC
    

    这会产生以下错误:

    ERROR: (gcloud.functions.deploy) OperationError: code=3, message=Function load error: File main.py that is expected to define function doesn't exist
    

    为了显式调用根目录作为源,我也尝试了与 #1 中相同的文件配置

    gcloud functions deploy NAME --source https://source.developers.google.com/projects/PROJECT_ID/repos/REPOSITORY_ID/moveable-aliases/BRANCH/paths/ --trigger-topic TOPIC
    

    它给了我与 #1 相同的错误:

    ERROR: (gcloud.functions.deploy) OperationError: code=3, message=Function load error: File main.py that is expected to define function doesn't exist
    

    在这个问题中使用原始文件结构(main.pyrequirements.txtpackage),我已经尝试了上面提供的部署语句。它解决了main.py not found 问题,但给了我上面原始问题中所述的错误

我还应该尝试什么?

【问题讨论】:

您的每个包目录中是否都有__init__.py 文件? 很高兴收到您的来信,达斯汀!是的,我有,但它们仍然是空白的。我应该如何填充它们以使其工作? 【参考方案1】:

您应该像这样构建您的应用程序:

.
├── main.py
├── package
│   ├── __init__.py
│   ├── script1.py
│   └── script2.py
├── package2
│   ├── __init__.py
│   ├── script3.py
│   └── script4.py
└── requirements.txt

那么在main.py,你可以这样做:

from package.script1 import foo
from package2.script2 import bar
# etc

【讨论】:

这正是我在 this post 中构建项目的方式,但 Google Cloud 在查找 main.py 时遇到问题 即使您从与main.py 相同的目录部署?它会产生什么错误? 您是否能够从本地文件系统而不是从云源存储库进行部署? 您的意思是使用“ZIP 上传”吗? GUI Google Cloud Functions“创建函数”页面上有 4 个选项:(1) 内联编辑器,(2) Zip 上传,(3) 从 Cloud Storage 压缩,&(4) Cloud Source 存储库 不,我的意思是直接使用gcloud 命令行工具,例如:gcloud functions deploy NAME --runtime python37 --trigger-topic TOPIC

以上是关于在 Google Cloud 函数中访问用户定义的包(ModuleNotFoundError: No module named...)的主要内容,如果未能解决你的问题,请参考以下文章

Google Cloud将用户添加到项目中

通过 API Key 访问 Google Cloud Function

从 Google Cloud Build 访问存储在 Google Secret Manager 中的环境变量

在与 Google Cloud IoT Core 交互时限制用户对 IoT 项目的访问

配置 Google Cloud Load Balancer 路径规则

Google Cloud Platform - 部署一个启动 webdriver 的云函数