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政策或違反了某些慣例? –