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を使用していませんが、すべてのプラットフォームで動作するスクリプトを書いています。

@FreddieChopin
これは修正されていますか? 2019年もまだ影響を受けているようです。

私がしなければならないのは、すべての\\/に手動で置き換えることです。

これは修正されていますか?

「これはバグではありません。機能です!」 (;

これは本当に奇妙なものです! これを変更したり、ドキュメントで(大きな文字で)言及したりできますか?

PR歓迎(ドキュメント用)

私は1つから始めましたが、それからこれを見つけました: 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、そしてそれは永遠に続くようです)が、スタータードキュメントのいくつかの「ヘッドアップ」は歓迎されます。

基本的な問題は、テンプレートの「パス」は実際にはOSパスではなく、「/」区切り文字のみが含まれていると予想されることです。 ただし、 loaders.get_source()では、 self.searchpathは、パス区切り文字が常に「/」であると見なします。

テンプレートパスを実際のOSパスに変更しないでください。これは、この標準的な仮定が使用されている場所が他にもあるためです。

解決策は、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 ...

このコードをWindows10 / Python 2.7で簡単にテストしたところ、「テンプレートが見つかりません」というエラーが修正されました。

このページは役に立ちましたか?
0 / 5 - 0 評価