在 Google App Engine 中跨模块导入
Import across modules in Google App Engine
我有一个 Python Google App Engine 项目,结构如下:
app/
handlers/
register_user.py
models/
user.py
user.py
文件包含 class User(ndb.Model)
.
我正在尝试从 register_user.py
访问 User
class 以创建新用户并将其放入数据库中。通常,我会像这样导入它:
from ..models.user import User
但是这个错误是因为我试图从我的根包上方导入一些东西 - 所以我猜 models 是我的根包,我无法返回到 app
包?
现在,我可以像这样导入来解决这个问题:
import importlib
User = importlib.import_module('models.user').User
不过我觉得这有点乱。那么 "right" 导入我的用户 class 的方法是什么?
编辑: 完整堆栈跟踪:
Attempted relative import beyond toplevel package (/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py:1552)
Traceback (most recent call last):
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1535, in __call__
rv = self.handle_exception(request, response, e)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1529, in __call__
rv = self.router.dispatch(request, response)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1278, in default_dispatcher
return route.handler_adapter(request, response)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1102, in __call__
return handler.dispatch()
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 572, in dispatch
return self.handle_exception(e, self.app.debug)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 570, in dispatch
return method(*args, **kwargs)
File "/base/data/home/apps/s~polly-chat/1.394430414829237783/main.py", line 48, in post
receive_message(messaging_event)
File "/base/data/home/apps/s~polly-chat/1.394430414829237783/messaging/handler.py", line 39, in receive_message
intent_picker.respond_to_postback(messaging_event)
File "/base/data/home/apps/s~polly-chat/1.394430414829237783/messaging/intent_picker.py", line 71, in respond_to_postback
intent = importlib.import_module('intents.register_user')
File "/base/data/home/runtimes/python27/python27_dist/lib/python2.7/importlib/__init__.py", line 37, in import_module
__import__(name)
File "/base/data/home/apps/s~polly-chat/1.394430414829237783/intents/register_user.py", line 1, in <module>
from ..models import messenger_user
ValueError: Attempted relative import beyond toplevel package
(这里的包名不同;我在上面简化了它们以使示例更通用)
我采用的方法是使用 the GAE 3rd party lib vendoring technique:
- 已创建
appengine_config.py
:
内容:
from google.appengine.ext import vendor
# Add any libraries installed in the "lib" folder.
vendor.add('lib')
- 创建了
/app/lib
目录
- 在
models
目录中添加了一个空的 __init__.py
文件以使其成为一个包
- placed/moved/symlinked
/app/lib
目录中的 models
目录
有了这个,可以使用以下方式引用模型:
from models.user import User
可能感兴趣:
- Define common files for GAE projects
我认为 Dan 走在正确的道路上,但是没有必要出售您自己的代码。 vendoring 系统是通过 pip 管理第三方依赖项,对于您的用例来说应该是完全不必要的,并且出售您自己的代码会违反约定。
根据您告诉我们的内容,您应该能够导入您的代码
from models import user
如果这不起作用,您应该找出原因,但您绝对不需要供应商扩展或 importlib 来解决它。
您的基础模块是您的基础 WSGI 应用程序所在的位置,这将由您的 app.yaml
路由到的位置定义。通常,您的 app.yaml
将包含如下内容:
- url: .* # This regex directs all routes to main.app
script: main.app
在这种情况下,在与 app.yaml
相同的目录中有一个 main.py
包含一个 app
WSGI 应用程序。在某些其他情况下,script
可能是 application.main.app
,在这种情况下,app
变量位于 application/main.py
中,然后应用程序目录将是基本目录。
每个包含模块的 Python 包都应该在其目录中包含一个 __init__.py
文件,正如 Dan 提到的那样。作为旁注,如果您确实为第三方代码使用 lib
目录,它将不包含 __init__.py
因为它不是 Python 包(只是一个包含 Python 包)。它不是包的事实是您使用 Dan 描述的供应商扩展来确保它包含的包在导入路径上的原因。
根据我的经验,很少需要相对导入,并且可能会让您遇到此类问题,所以我会避免它们。
如果您仍然遇到困难,请布置您应用程序的整个文件结构,包括 app.yaml
内容和每个子目录,包括它们是否包含 __init__.py
。
我有一个 Python Google App Engine 项目,结构如下:
app/
handlers/
register_user.py
models/
user.py
user.py
文件包含 class User(ndb.Model)
.
我正在尝试从 register_user.py
访问 User
class 以创建新用户并将其放入数据库中。通常,我会像这样导入它:
from ..models.user import User
但是这个错误是因为我试图从我的根包上方导入一些东西 - 所以我猜 models 是我的根包,我无法返回到 app
包?
现在,我可以像这样导入来解决这个问题:
import importlib
User = importlib.import_module('models.user').User
不过我觉得这有点乱。那么 "right" 导入我的用户 class 的方法是什么?
编辑: 完整堆栈跟踪:
Attempted relative import beyond toplevel package (/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py:1552)
Traceback (most recent call last):
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1535, in __call__
rv = self.handle_exception(request, response, e)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1529, in __call__
rv = self.router.dispatch(request, response)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1278, in default_dispatcher
return route.handler_adapter(request, response)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 1102, in __call__
return handler.dispatch()
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 572, in dispatch
return self.handle_exception(e, self.app.debug)
File "/base/data/home/runtimes/python27/python27_lib/versions/third_party/webapp2-2.5.2/webapp2.py", line 570, in dispatch
return method(*args, **kwargs)
File "/base/data/home/apps/s~polly-chat/1.394430414829237783/main.py", line 48, in post
receive_message(messaging_event)
File "/base/data/home/apps/s~polly-chat/1.394430414829237783/messaging/handler.py", line 39, in receive_message
intent_picker.respond_to_postback(messaging_event)
File "/base/data/home/apps/s~polly-chat/1.394430414829237783/messaging/intent_picker.py", line 71, in respond_to_postback
intent = importlib.import_module('intents.register_user')
File "/base/data/home/runtimes/python27/python27_dist/lib/python2.7/importlib/__init__.py", line 37, in import_module
__import__(name)
File "/base/data/home/apps/s~polly-chat/1.394430414829237783/intents/register_user.py", line 1, in <module>
from ..models import messenger_user
ValueError: Attempted relative import beyond toplevel package
(这里的包名不同;我在上面简化了它们以使示例更通用)
我采用的方法是使用 the GAE 3rd party lib vendoring technique:
- 已创建
appengine_config.py
:
内容:
from google.appengine.ext import vendor
# Add any libraries installed in the "lib" folder.
vendor.add('lib')
- 创建了
/app/lib
目录 - 在
models
目录中添加了一个空的__init__.py
文件以使其成为一个包 - placed/moved/symlinked
/app/lib
目录中的models
目录
有了这个,可以使用以下方式引用模型:
from models.user import User
可能感兴趣:
- Define common files for GAE projects
我认为 Dan 走在正确的道路上,但是没有必要出售您自己的代码。 vendoring 系统是通过 pip 管理第三方依赖项,对于您的用例来说应该是完全不必要的,并且出售您自己的代码会违反约定。
根据您告诉我们的内容,您应该能够导入您的代码
from models import user
如果这不起作用,您应该找出原因,但您绝对不需要供应商扩展或 importlib 来解决它。
您的基础模块是您的基础 WSGI 应用程序所在的位置,这将由您的 app.yaml
路由到的位置定义。通常,您的 app.yaml
将包含如下内容:
- url: .* # This regex directs all routes to main.app
script: main.app
在这种情况下,在与 app.yaml
相同的目录中有一个 main.py
包含一个 app
WSGI 应用程序。在某些其他情况下,script
可能是 application.main.app
,在这种情况下,app
变量位于 application/main.py
中,然后应用程序目录将是基本目录。
每个包含模块的 Python 包都应该在其目录中包含一个 __init__.py
文件,正如 Dan 提到的那样。作为旁注,如果您确实为第三方代码使用 lib
目录,它将不包含 __init__.py
因为它不是 Python 包(只是一个包含 Python 包)。它不是包的事实是您使用 Dan 描述的供应商扩展来确保它包含的包在导入路径上的原因。
根据我的经验,很少需要相对导入,并且可能会让您遇到此类问题,所以我会避免它们。
如果您仍然遇到困难,请布置您应用程序的整个文件结构,包括 app.yaml
内容和每个子目录,包括它们是否包含 __init__.py
。