0

我有一个Python的谷歌应用程序引擎项目结构如下:导入跨模块在谷歌应用程序引擎

app/ 
    handlers/ 
     register_user.py 
    models/ 
     user.py 

user.py文件包含一个类User(ndb.Model)

我试图从register_user.py访问User类来创建数据库并将新用户放入数据库。通常情况下,我只希望导入这样的:

from ..models.user import User 

但这样的错误,因为我想从我的根包以上进口的东西 - 所以我猜模特是我的根包,我可以没有回到app包?

现在,我能够通过导入这样来解决它:

import importlib 
User = importlib.import_module('models.user').User 

我觉得这是一种杂乱,虽然。那么导入我的用户类的“正确”方式是什么?

编辑:完整的堆栈跟踪:

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 

(这里的包名不同,我简化他们上面让这个例子更普遍)

+0

请发布您正在追踪的追踪**全文**。 – MattDMo

+1

我不确定我是否理解,但是如果从models.user导入用户' –

+0

@ joelgoldstick会发生什么? –

回答

1

我觉得丹是在正确的轨道上,但有没有必要提供您自己的代码。销售系统是用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中,然后应用程序目录将成为基础目录。

如Dan所述,每个包含模块的Python程序包应在其目录中包含__init__.py文件。作为旁注,如果你使用lib目录作为第三方代码,它将不包含__init__.py,因为它不是一个Python包(只是一个包含Python包的目录)。它不是一个包的原因是你使用供应商扩展Dan所描述的,以确保它包含的包在导入路径中。

根据我的经验,相对进口很少需要,可以让你陷入这样的问题,所以我会避免它们。

如果仍然卡住,请将应用程序的整个文件结构(包括app.yaml内容)和每个子目录(包括是否包含__init__.py)进行布局。

+0

我想我以前是在做我的非相对进口产品,但现在他们工作了! '从models.user import User正确地从'register_user.py'导入。 –

0

我走近这个问题的方法是使用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 DIR
  • 加入空__init__.py文件中的models目录使之成为包装
  • 放置/移动/符号链接的models dir中/app/lib内部dir

有了这个该模型可以使用被引用:

from models.user import User 

可能感兴趣的:

+0

供应商是针对第三方代码的,应该不需要为自己的代码使用供应商扩展(实际上这样做首先违反了它的约定)。 –

+0

@BillPrin我承认,我发现它很方便,只是为了它。 “违反惯例”是指什么?违反了某些Google政策或违反了某些惯例? –