googleappengine:导入处理程序范围内的模块与全局范围内的模块

2024-09-28 17:23:53 发布

您现在位置:Python中文网/ 问答频道 /正文

我的项目由许多导入组成,这些导入被放在“全局”范围内。你知道吗

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

我只想在特定的处理程序中使用datetime模块一次。我应该在处理程序中导入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() 

似乎本地导入显示了更清晰的依赖关系。是否有任何性能问题或其他缺点需要考虑?你知道吗


Tags: 项目fromimport处理程序datetimeherelogginghandlers
3条回答

像这样隐藏导入是一种优化;每当考虑是否优化时,请验证所建议的优化是否真的有效。你知道吗

让我们先考虑一下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)])

如果访问“/”url,我们将看到以下输出:

The datetime module is already loaded.

706 modules have been loaded

95 standard library modules have been loaded

207 appengine modules have been loaded

即使在这个最小的应用程序中,datetime也已经被SDK导入了。一旦Python导入了一个模块,以后的导入只需要查找一个字典,因此隐藏导入没有任何好处。鉴于SDK已经导入了95个标准库模块和207个SDK模块,因此隐藏常用标准库或SDK模块的导入不太可能有什么好处。你知道吗

这就留下了导入应用程序代码的问题。可以通过在路由中将处理程序声明为字符串来延迟加载处理程序,以便在访问路由之前不会导入它们:

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

这种技术允许优化启动时间,而无需在类或方法中隐藏导入,如果您发现有必要的话。你知道吗

其他答案指出,延迟加载的代价可能是意外的运行时错误。此外,如果选择隐藏导入,还可能降低代码可读性,可能导致结构性问题,例如屏蔽循环依赖,并为经验不足的开发人员树立了一个糟糕的榜样,他们可能认为隐藏导入是惯用的,而不是优化。你知道吗

因此,在考虑以这种方式进行优化时:

  • 确认优化是必要的:并非所有应用程序都需要绝对的最大性能
  • 验证是否解决了正确的问题;appengine上的RPC调用往往主导响应时间
  • 配置文件以验证优化是否有效
  • 考虑代码可维护性的成本

我希望,依赖SDK的sys.modules类似于云运行时是一个合理的假设。你知道吗

在处理程序内部导入(或者甚至在get()函数内部导入,如果您愿意的话)没有问题—我大量使用它。你知道吗

延迟加载的优点:

  • 缩短应用程序加载时间
  • 如果在初始化时加载所有模块,即使是很少使用的模块,应用程序的平均内存占用也可能比所需的总内存占用小得多—成本更低

延迟加载的缺点:

  • 不确定的应用程序加载时间
  • 由于具体情况未知,在延迟模块加载时可能遇到难以重现的错误

相关(仅在延迟加载意义上):App Engine: Few big scripts or many small ones?

您应该大胆地在文件的开头导入模块,这将把它绑定到该文件的作用域中。我认为你所做的是所谓的'延迟加载'的模块,它可以导致错误在运行时,如果模块没有安装或导入正确。你知道吗

顺便说一下,python的工作方式是,每次导入模块时,解释器都会查看模块是否已经导入。如果它已经被导入,那么它将设置对它的引用。换句话说,它不会创建它的新实例。你知道吗

我建议您为您的处理程序类创建一个文件,并在该文件的开头导入datetime和任何您想要的内容。你知道吗

相关问题 更多 >