Jinja: FileSystemLoader не работает с путями Windows (обратными косыми чертами)

Созданный на 7 сент. 2017  ·  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
  • Версия Джинджа: 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 по умолчанию возвращает путь с «\» в окнах. Я знаю, что это правильное поведение, но встроенная функция, такая как «открыть», принимает как косую, так и обратную косую черту, поэтому «иногда это работает, иногда — нет». Вероятно, нам нужен какой-то способ обработки путей, независимых от платформ... своего рода "соглашение Python для внутренней обработки путей"... Я думаю, что это не проблема jinja2 (это проблема исторического соглашения между Unix и Windows, и это кажется вечным), но приветствуются некоторые «заголовки» в стартовых документах.

Основная проблема заключается в том, что «путь» шаблона на самом деле не является путем ОС, а должен содержать только разделители «/». Но в loaders.get_source() self.searchpath также считает, что разделителем путей всегда является «/».

Пути шаблонов не следует изменять, чтобы они были фактическими путями ОС, потому что, по-видимому, есть и другие места, где используется это каноническое предположение.

Решение состоит в том, чтобы изменить как шаблон, так и путь поиска, чтобы они содержали фактические разделители путей ОС в той точке, где пути ОС необходимы:

    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 рейтинги