无法在 Google App Engine 上使用 jinja2 PackageLoader

4 投票
1 回答
3619 浏览
提问于 2025-04-17 20:17

我正在尝试使用 jinja2 提供的 PackageLoader,但我无法让它正常工作。

在我的 app.yaml 文件中,我已经声明了所需的库:

libraries:
- name: jinja2
  version: latest
- name: setuptools
  version: latest

这是我能创建的最简单的例子:

import webapp2, sys
from jinja2 import Environment, PackageLoader
sys.path += ['lib/somepackage']

class Test(webapp2.RequestHandler):
    def get(self):
        env = Environment(loader=PackageLoader('common'))
        self.response.write(env.get_template('test.html').render())

routes = [(r"/", Test)]
app = webapp2.WSGIApplication(routes, debug=True)

common 存在于目录 lib/somepackage 中,并且有一个包 templates,里面有一个文件 test.html。这个 HTML 文件只包含了文字 'test'。

当我构建 PackageLoader 时,它的 provider 在 Google App Engine 中总是显示为 NullProvider。当我手动请求一个提供者时,我得到了 DefaultProvider,所以显然这里有问题。

为了请求一个提供者,我确保 lib/somepackagesys.path 中,通过进入那个目录,然后:

>>> import pkg_resources
>>> provider = pkg_resources.get_provider('common')
>>> provider
<pkg_resources.DefaultProvider instance at 0x8490b2c>

当在 Google App Engine 中这失败时,相关的错误信息如下:

  File "/<>/test/main.py", line 7, in get
    self.response.write(env.get_template('test.html').render())
  File "/<>/google_appengine/lib/jinja2-2.6/jinja2/environment.py", line 719, in get_template
    return self._load_template(name, self.make_globals(globals))
  File "/<>/google_appengine/lib/jinja2-2.6/jinja2/environment.py", line 693, in _load_template
    template = self.loader.load(self, name, globals)
  File "/<>/google_appengine/lib/jinja2-2.6/jinja2/loaders.py", line 115, in load
    source, filename, uptodate = self.get_source(environment, name)
  File "/<>/google_appengine/lib/jinja2-2.6/jinja2/loaders.py", line 226, in get_source
    if not self.provider.has_resource(p):
  File "/<>/google_appengine/lib/setuptools-0.6c11/pkg_resources.py", line 1170, in has_resource
    return self._has(self._fn(self.module_path, resource_name))
  File "/<>/google_appengine/lib/setuptools-0.6c11/pkg_resources.py", line 1218, in _has
    "Can't perform this operation for unregistered loader type"
NotImplementedError: Can't perform this operation for unregistered loader type

不过,当我使用 FileSystemLoader 时,它是可以工作的,但我想这在压缩包中是行不通的:

import common.templates
env = Environment(loader=FileSystemLoader(common.templates.__path__))

我看到过 这个 StackOverflow 问题,但这不是我遇到的问题。

更新:

我刚在 1.7.6 SDK 中测试了这个例子,它是可以工作的,但我希望能在旧的 SDK(或者 old_dev_appserver)上看到它也能正常工作。

1 个回答

7

我觉得问题出在 pkg_resources 上。

在 Google App Engine(GAE)中,有些和 os 相关的功能并没有实现,但看起来是 jinja2 或者 Google 提供了一些解决办法。

这些链接说明了这个问题:

http://code.google.com/p/googleappengine/issues/detail?id=60

https://github.com/mitsuhiko/jinja2/issues/143

Jinja2 的 PackageLoader 在 Google App Engine 上

https://bitbucket.org/tarek/distribute/issue/73/pkg_resources-fails-on-google-app-engine

我用过

jinja_environment = jinja2.Environment(autoescape=True,
loader=jinja2.FileSystemLoader(os.path.join(os.path.dirname(__file__), 'templates')))

作为模板,来从与定义文件同一目录下的 "template" 目录中获取模板。但是问题是关于打包成 eggs 的文件,以及使用 PackageLoader

包里面有 __init__.py 文件吗? 不过你说在 1.7.6 版本上是可以工作的。

撰写回答