Google AppEngine dev_appserver 尽管软件包安装在 virtualenv 中并且在 Google Cloud SDK 中可用,但仍引发 ImportError

Google AppEngine dev_appserver raises ImportError despite package being installed in virtualenv and available in Google Cloud SDK

我正在开发一个 Google AppEngine 项目,该项目使用遗留的 Python 2.7 运行时 - 我的团队正在远离它,但我们暂时仍在使用它。在过去的 ~6 个月里,本地开发对我来说运行良好,我团队中没有其他人受到以下问题的影响。

我在启动 dev_appserver.py 以及处理任何请求期间收到 ImportError

09:36:59 dev_server.1    | ERROR    2021-05-13 13:36:59,470 wsgi.py:269] 
09:36:59 dev_server.1    | Traceback (most recent call last):
09:36:59 dev_server.1    |   File "/Users/me/google-cloud-sdk/platform/google_appengine/google/appengine/runtime/wsgi.py", line 240, in Handle
09:36:59 dev_server.1    |     handler = _config_handle.add_wsgi_middleware(self._LoadHandler())
09:36:59 dev_server.1    |   File "/Users/me/google-cloud-sdk/platform/google_appengine/google/appengine/runtime/wsgi.py", line 311, in _LoadHandler
09:36:59 dev_server.1    |     handler, path, err = LoadObject(self._handler)
09:36:59 dev_server.1    |   File "/Users/me/google-cloud-sdk/platform/google_appengine/google/appengine/runtime/wsgi.py", line 85, in LoadObject
09:36:59 dev_server.1    |     obj = __import__(path[0])
09:36:59 dev_server.1    |   File "/Users/me/Source/myproject/main.py", line 5, in <module>
09:36:59 dev_server.1    |     import webapp2
09:36:59 dev_server.1    |   File "/Users/me/google-cloud-sdk/platform/google_appengine/lib/webapp2-2.5.2/webapp2.py", line 25, in <module>
09:36:59 dev_server.1    |     import webob
09:36:59 dev_server.1    |   File "/private/var/folders/qs/2qn9hbhn3k77wbhgsg77w6tm0000gn/T/pip-target-etkWjd/lib/python/webob/__init__.py", line 1, in <module>
09:36:59 dev_server.1    |   File "/Users/me/google-cloud-sdk/platform/google_appengine/google/appengine/tools/devappserver2/python/runtime/sandbox.py", line 1168, in load_module
09:36:59 dev_server.1    |     raise ImportError('No module named %s' % fullname)
09:36:59 dev_server.1    | ImportError: No module named webob.datetime_utils

如您所见,错误发生在导入 webapp2 时,它调用 import webobwebob 都安装在我的 virtualenv 中:

(myenv) me@pegasus site % pip list | grep WebOb
WebOb                         1.8.7

以及app.yaml中指定的:

libraries:
...
- name: webob
  version: "1.2.3"
...

我已确保我的 virtualenv 在我启动时处于活动状态 dev_appserver.py

令我好奇的是这行回溯:

09:36:59 dev_server.1  |  File "/private/var/folders/qs/2qn9hbhn3k77wbhgsg77w6tm0000gn/T/pip-target-etkWjd/lib/python/webob/__init__.py", line 1, in <module>

我不知道为什么要执行 /private/var/folders 中的代码 - 它不应该调用我的 virtualenv 中的代码或 Google Cloud SDK 提供的代码吗?

它似乎在 SDK 中 - 调用者是 google-cloud-sdk/platform/google_appengine/lib/webapp2-2.5.2/webapp2.py,但是我找不到任何理由说明为什么 webob 的解析路径在 /private/var/folders 而不是我的 virtualenv,或者更明智地说,webob-1.2.3 包也位于 google-cloud-sdk/platform/google_appengine/lib/!

事实上,在 ~6 年的全职开发 Python 中,我从未在回溯中看到过这样的文件路径 - 我总是希望执行的代码在我自己的文件中或 site-packages 关联的 virtualenv.

此外,回溯中的文件不存在(或者至少对我不可见):尝试 ls /private/var/folders/qs/2qn9hbhn3k77wbhgsg77w6tm0000gn/T/pip-target-etkWjd/ 目录导致 No such file or directory .

我试过的:

  1. 完全删除并重新安装了我的 virtualenv 和 Google Cloud SDK。
  2. 删除了 webobpip 安装实例。
  3. 使用 SDK (1.2.3) 附带的相同版本重新安装 webob
  4. 使用 pyenv 安装了 python2.7 的新实例,并使用它删除并重新创建了我的 virtualenv。
  5. 从我的 PATH 中删除了所有无关条目,以查看是否某些条目导致导入系统以意外方式解析 webob

None 这已经奏效了。最终,我仍然不确定如果软件包安装在活动的 virtualenv 中,导入怎么会失败——我希望 Google Cloud SDK 中的 webapp2 模块会通过以下方式解析导入virtualenv,但我绝对不是导入系统的专家。

在尝试导入 webob 之前,我最终将以下代码添加到 /Users/me/google-cloud-sdk/platform/google_appengine/lib/webapp2-2.5.2/webapp2.py

import imp
fp, pathname, description = imp.find_module('webob')
print '--------------------------'
print fp
print pathname
print description
print '--------------------------'

其中打印出:

14:03:13 dev_server.1    |--------------------------
14:03:13 dev_server.1    | None
14:03:13 dev_server.1    | /Users/me/Source/myproject/lib/webob
14:03:13 dev_server.1    | ('', '', 5)
14:03:13 dev_server.1    | --------------------------

lib 中的这个 webob 目录是意外的 - 它包含在 GAE 和 SDK 中的 python2 运行时中,因此不需要在lib。它也是空的,所以我没有注意到它,因为 git 没有报告任何新的未跟踪文件。

我不太确定这个机制,但这导致了导入问题 - 我删除空目录后,问题就解决了。