2017-10-12 80 views
0

我的項目由大量位於'全局'範圍內的導入組成。Google App Engine:在處理程序範圍內導入模塊與全局範圍

from google.appengine.ext import ndb 
from handlers import SomeHandler 
import logging 
import datetime # will only use this module ONCE 

我想用datetime模塊只是一次特定的處理器中。我應該在處理程序中導入日期時間還是應該將其保留在全局範圍內?

import datetime # Should we import here? 

class BookHandler(webapp2.RequestHandler): 
    import datetime # Or, should we import here? 
    def get(self): 
     today = datetime.datetime.now() 

看起來像導入本地顯示更清晰的依賴關係。是否有任何性能問題或其他缺點需要考慮?

回答

1

你應該在你的文件的開始處挑剔地導入模塊,它將它綁定到該文件的範圍。我認爲你正在做的事情叫做「延遲加載」模塊,如果模塊沒有正確安裝或導入,它會在運行時導致錯誤。

順便說一下,python的工作方式是,每當你導入一個模塊時,解釋器看起來是否已經導入了模塊。如果它已經被導入,那麼它會設置一個對它的引用。換句話說,它不會創建一個新的實例。

我推薦的是爲你的處理程序類創建一個文件,並在該文件的開始處導入日期時間以及任何你想要的東西。

1

在處理程序內部導入沒有問題(如果您願意,甚至可以在get()函數內部導入) - 我正在大量使用它。延遲加載的

優點:

  • 減少應用程序的加載時間
  • 您的應用程序的平均內存佔用量可能比您應該加載在啓動時,所有模塊所需的總內存佔用低得多,甚至那些很少使用的 - 成本更低的延遲加載的

缺點:

  • 非確定性的應用程序加載時間
  • 潛力難以重現bug在延遲加載模塊創下自確切條件是未知

相關(在延遲加載感只):App Engine: Few big scripts or many small ones?

1

像這樣隱藏進口是一種優化;每當考慮是否優化時,驗證提議的優化是否真的有效。

我們首先考慮datetime的具體示例。這裏有一個簡單的應用程序:

import sys 

import webapp2 


class Handler(webapp2.RequestHandler): 

    def get(self): 
     if 'datetime' in sys.modules: 
      self.response.write('The datetime module is already loaded.\n') 
     else: 
      self.response.write('The datetime module is not already loaded\n.') 
     self.response.write('%d modules have been loaded\n' % len(sys.modules)) 
     count = sum(1 for x in sys.modules.values() if '/lib64' in repr(x)) 
     self.response.write('%d standard library modules have been loaded\n' % count) 
     gcount = sum(1 for x in sys.modules.values() if 'appengine' in repr(x)) 
     self.response.write('%d appengine modules have been loaded\n' % gcount) 

application = webapp2.WSGIApplication([('/', Handler)]) 

如果我們參觀「/」的網址,我們看到這樣的輸出:

datetime模塊已經加載。

706模塊已經載入

95標準庫模塊已經載入

207的AppEngine模塊已經載入

即使在這個最小的應用程序,datetime已經由SDK進口*。一旦Python導入了一個模塊,進一步的導入只花費一次字典查找,所以隱藏導入沒有任何好處。由於SDK已經導入了95個標準庫模塊和207個SDK模塊,因此隱藏導入常用標準庫或SDK模塊的可能性不大。

這留下了導入應用程序代碼的問題。處理程序可以延遲加載通過聲明他們作爲路線字符串,這樣直到路線參觀他們沒有進口:

app = webapp2.Application([('/foo', 'handlers.FooHandler')]) 

這種技術允許優化啓動時間不隱藏在類或方法的進口,你應該找這是必要的。

其他答案指出,延遲加載的代價可能是意外的運行時錯誤。此外,如果您選擇隱藏導入,它也會降低代碼可讀性,可能導致結構性問題,例如掩蓋循環依賴性,併爲經驗較少的開發人員設置一個不好的示例,他們可能會認爲隱藏導入是慣用的而不是優化。

因此,考慮以這種方式優化時:

  • 驗證優化是必要的:不是所有的應用程序都需要絕對最大性能
  • 驗證正確的問題正在得到解決;在App Engine上的RPC調用往往主宰響應時間
  • 配置文件以驗證優化是有效
  • 考慮代碼的可維護性

*費用依託SDK的sys.modules是相似的我希望雲運行時是一個合理的假設。