Jinja: FileSystemLoader 不适用于 Windows 路径(反斜杠)

创建于 2017-09-07  ·  9评论  ·  资料来源: pallets/jinja

预期行为

在 Windows 上FileSystemLoader应该允许 Windows 样式(带有\ )和 UNIX 样式(带有/ )路径。

实际行为

在 Windows 上,当使用FileSystemLoader时,以下失败:
jinjaEnvironment.get_template('.\source\architecture\ARM\ARMv6-M-ARMv7-M\bo ardTemplates\ARMv6-M-ARMv7-M.metadata')

jinja2.exceptions.TemplateNotFound: .\source\architecture\ARM\ARMv6-M-ARMv7-M\bo ardTemplates\ARMv6-M-ARMv7-M.metadata

虽然这jinjaEnvironment.get_template('.\source\architecture\ARM\ARMv6-M-ARMv7-M\bo ardTemplates\ARMv6-M-ARMv7-M.metadata'.replace('\\', '/'))工作得很好。

完整回溯

Traceback (most recent call last):
  File "./scripts/generateBoard.py", line 186, in <module>
    metadata = jinjaEnvironment.get_template(metadataFile).render(dictionary = d
ictionary)
  File "C:\Python27\lib\site-packages\jinja2\environment.py", line 830, in get_t
emplate
    return self._load_template(name, self.make_globals(globals))
  File "C:\Python27\lib\site-packages\jinja2\environment.py", line 804, in _load
_template
    template = self.loader.load(self, name, globals)
  File "C:\Python27\lib\site-packages\jinja2\loaders.py", line 113, in load
    source, filename, uptodate = self.get_source(environment, name)
  File "C:\Python27\lib\site-packages\jinja2\loaders.py", line 168, in get_sourc
e
    pieces = split_template_path(template)
  File "C:\Python27\lib\site-packages\jinja2\loaders.py", line 31, in split_temp
late_path
    raise TemplateNotFound(template)
jinja2.exceptions.TemplateNotFound: .\source\architecture\ARM\ARMv6-M-ARMv7-M\bo
ardTemplates\ARMv6-M-ARMv7-M.metadata

你的环境

  • Python版本:2.7.12
  • Jinja 版本:2.9.6

最有用的评论

如果您不打算修复它,我认为应该在文档中用粗体字明确说明这些信息。 并不是我故意使用反斜杠 - 当使用其他一些 python 代码生成文件名时(例如通过在文件夹中搜索适当的扩展名),字符串具有系统的本机斜杠(因此在 Windows 上是反斜杠)。 在这种情况下,您必须明确替换斜杠...

顺便说一句 - 我没有使用 Windows,但我正在编写一个可以在所有平台上运行的脚本。

所有9条评论

Jinja 模板名称不是文件系统路径(即使它们在仅使用 FileSystemLoader 时映射到文件系统路径)。 他们总是使用正斜杠,所以这是按预期工作的。

如果您不打算修复它,我认为应该在文档中用粗体字明确说明这些信息。 并不是我故意使用反斜杠 - 当使用其他一些 python 代码生成文件名时(例如通过在文件夹中搜索适当的扩展名),字符串具有系统的本机斜杠(因此在 Windows 上是反斜杠)。 在这种情况下,您必须明确替换斜杠...

顺便说一句 - 我没有使用 Windows,但我正在编写一个可以在所有平台上运行的脚本。

@弗雷迪肖邦
这个是固定的吗? 似乎在 2019 年仍然影响着我。

我要做的是将所有\\手动替换为/

这个是固定的吗?

“这不是错误 - 这是一个功能!” (;

这真是一件很奇怪的事! 请问可以在文档中更改或提及(大写字母)吗?

PR 欢迎(对于文档)

我从一个开始,但后来我发现了这个: https ://github.com/pallets/jinja/blob/master/jinja2/loaders.py#L43 -L61

A very basic example for a loader that looks up templates on the file
system could look like this::
    from jinja2 import BaseLoader, TemplateNotFound
    from os.path import join, exists, getmtime
    class MyLoader(BaseLoader):
        def __init__(self, path):
            self.path = path
        def get_source(self, environment, template):
            path = join(self.path, template)
            if not exists(path):
                raise TemplateNotFound(template)
            mtime = getmtime(path)
            with file(path) as f:
                source = f.read().decode('utf-8')
            return source, path, lambda: mtime == getmtime(path)

文档明确说应该/可以使用 os.path.join 。 也许一个问题更合适?

真正的问题是 python 路径模块默认在 Windows 上返回带有 '\' 的路径。 我知道这是正确的行为,但是像“open”这样的内置函数同时接受斜杠和反斜杠,所以“有时它有效,有时它不”这样的事情就会发生。 可能我们需要某种方法来处理独立于平台的路径......某种“python 约定在内部处理路径”之类的东西......我认为这不是 jinja2 的问题(这是历史惯例的问题Unix 和 Windows,它似乎永远存在),但欢迎在入门文档中添加一些“提醒”。

根本问题是模板“路径”并不是真正的操作系统路径,而是预计只包含“/”分隔符。 但是在 loaders.get_source ()中, self.searchpath也认为路径分隔符总是“/”。

不应将模板路径更改为实际的操作系统路径,因为显然在其他地方使用了这种规范假设。

解决方案是在需要 OS 路径的地方同时更改模板和搜索路径以包含实际的 OS 路径分隔符:

    def get_source(self, environment, template):
        _searchpaths = self.searchpath
        if path.sep != '/':
            template = template.replace('/', path.sep)
            _searchpaths = [p.replace('/', path.sep) for p in self.searchpath]
        pieces = os.path.split(template)
        for searchpath in _searchpaths:
            # Existing code continues here ...

我在 Windows 10/Python 2.7 中简要测试了这段代码,它纠正了我的“找不到模板”错误。

此页面是否有帮助?
0 / 5 - 0 等级