Python 如何在Jinja2宏中引发异常?

Python 如何在Jinja2宏中引发异常?,python,jinja2,salt-stack,Python,Jinja2,Salt Stack,我有一个宏,用于使用构建本地存储库 下面是代码片段: {%- set gnupghome = kwargs.pop('gnupghome', '/root/.gnupg') %} {%- set env = { 'GNUPGHOME': gnupghome } %} keyring_import: cmd: - run {%- if 'keyid' in kwargs and 'keyserver' in kwargs %} {%- set keyid = kwargs.po

我有一个宏,用于使用构建本地存储库

下面是代码片段:

{%- set gnupghome = kwargs.pop('gnupghome', '/root/.gnupg') %}
{%- set env = { 'GNUPGHOME': gnupghome } %}
keyring_import:
  cmd:
    - run
{%- if 'keyid' in kwargs and 'keyserver' in kwargs %}
    {%- set keyid = kwargs.pop('keyid') %}
    {%- set keyserver = kwargs.pop('keyserver') %}
    - name: 'gpg --no-default-keyring --keyring {{ gnupghome }}/trustedkeys.gpg --keyserver {{ keyserver }} --recv-keys {{ keyid }}'
{%- elif 'key_url' in kwargs %}
    {%- set key_url = kwargs.pop('key_url') %}
    - name: 'wget -q -O- "{{ key_url }}" | gpg --no-default-keyring --keyring {{ gnupghome }}/trustedkeys.gpg --import'
{%- endif %}
    - require:
      - pkg: wget
      - pkg: gnupg
endif
关键字处,我想使用
else
引发异常,例如:

需要密钥url或密钥服务器和密钥ID


有可能吗?

这可以在扩展中处理。从

将扩展传递给您的环境:
jinja2.Environment(…extensions=[RaiseExtension])
然后在模板中使用它:

{%- if 'keyid' in kwargs and 'keyserver' in kwargs %}
    ...
{%- else %}
    {% raise "Either key_url or both keyserver and keyid required." %}
{% endif %}
{{ raise("uh oh...") }}

塞雷内维院长的回答很优雅。下面是一个较短的解决方案,它为jinja的环境添加了一个全局变量

def raise_helper(msg):
    raise Exception(msg)

env = jinja2.Environment(...
env.globals['raise'] = raise_helper
然后在模板中:

{%- if 'keyid' in kwargs and 'keyserver' in kwargs %}
    ...
{%- else %}
    {% raise "Either key_url or both keyserver and keyid required." %}
{% endif %}
{{ raise("uh oh...") }}

超级快速的解决方法,只要您不介意引发
ZeroDivisionError

在要引发异常的任何位置插入一个
{{0/0}

插入一个
{{“此处解释的我的错误”/0}
表达式。e、 g

{% if not required_parameter %}
{{ "required_parameter must be defined."/0 }}
{% endif %}

(基于zsero的0/0答案)

如果这是由Ansible完成的,Ansible会将过滤器添加到Jinja,可用于:

{{ ('OK text' if condition_ok) | mandatory('Text of error message') }}
给出了失败的原因:

fatal: [hostname]: FAILED! => {"msg": "Text of error message"}

(用您需要进行的检查来替换
条件\u ok
'ok text'
可以是
'

我还想从jinja2模板中抛出一个异常,并显示一条错误消息,但是没有任何外部依赖项(全局/扩展)。我最终得到了这个宏:

{% macro abort(error) %}
    {{ None['[ERROR] ' ~ error][0] }}
{% endmacro %}
使用:

{{ abort("Either key_url or both keyserver and keyid required.") }}  
它提供了一个堆栈跟踪,但有以下异常:

jinja2.exceptions.UndefinedError: 'None' has no attribute '[ERROR] Either key_url or both keyserver and keyid required.'

另一个打印给定值的快速破解:

{% include 'error: ' ~ value_to_print %}
结果:

jinja2.exceptions.TemplateNotFound: error: abc

不,Jinja2不支持引发异常。您可以使用python函数或筛选器,它们可以引发异常,但不能在纯Jinja中使用。这并没有真正提供一个有用的错误——对我来说,它会生成错误文本:“/:'str'和'int'不支持的操作数类型”。这是因为它非常简单。谢谢