【问题标题】:Calling function from a module in python从python中的模块调用函数
【发布时间】:2021-01-06 12:16:52
【问题描述】:

我正在编写一个 python 脚本来从另一个文件中调用一个文件中的一个变量。这是一个 IAM 用户的 IAM 策略。我有一个函数调用另一个文件中的变量 带有该函数的文件名为“template_utils.py”。我想要 JSON 格式的输出。我不确定是什么问题。

import sys
import json
import time 
import meta_templates
from jinja2 import Template
def create_aws_iam_policy_template(**kwargs):
  template_data = {}
  template_data["region"] = kwargs.get('region')
  template_data["instance_types"] = kwargs.get('instance_type')
  template_data["ebs_volume_size"] = kwargs.get('ebs_volume_size')
  template_data["meta_template_name"] = kwargs.get('meta_template_name')

  meta_template_dict = getattr(meta_templates, template_data["meta_template_name"])
  meta_template_json = json.dumps(meta_template_dict)
  template_json = meta_template_json.format(template_data)
  return template_json  

template_json = create_aws_iam_policy_template(
  region="us-east2",
  instance_type="t2.micro",
  ebs_volume_size=20,
  meta_template_name="ec2_policy_meta_template"
)

打印(template_json)

这是策略名为“meta_template.py”的文件

import json
from jinja2 import Template
ec2_policy_meta_template = { 
        "Version": "2012-10-17",
        "Statement": [
            {
                "Sid": "VisualEditor0",
                "Effect": "Allow",
                "Action": "ec2:RunInstances",
                "Resource": [
                    "arn:aws:ec2:{{region}}::instance/*",
                    "arn:aws:ec2:{{region}}::network-interface/*",
                    "arn:aws:ec2:{{region}}::key-pair/*",
                    "arn:aws:ec2:{{region}}::security-group/*",
                    "arn:aws:ec2:{{region}}::subnet/*",
                    "arn:aws:ec2:{{region}}::volume/*",
                    "arn:aws:ec2:{{region}}::image/ami-*"
                ],
                "Condition": {
                    "ForAllValues:NumericLessThanEquals": {
                        "ec2:VolumeSize": "{{ebs_volume_size}}"
                    },
                    "ForAllValues:StringEquals": {
                        "ec2:InstanceType": "{{instance_type}}"
                    }
                }
            },
            {
                "Sid": "VisualEditor1",
                "Effect": "Allow",
                "Action": [
                    "ec2:TerminateInstances",
                    "ec2:StartInstances",
                    "ec2:StopInstances"
                ],
                "Resource": "arn:aws:ec2:{{region}}::instance/*",
                "Condition": {
                    "ForAllValues:StringEquals": {
                        "ec2:InstanceType": "{{instance_type}}"
                    }
                }
            },
            {
                "Sid": "VisualEditor2",
                "Effect": "Allow",
                "Action": [
                    "ec2:Describe*",
                    "ec2:GetConsole*",
                    "cloudwatch:DescribeAlarms",
                    "iam:ListInstanceProfiles",
                    "cloudwatch:GetMetricStatistics",
                    "ec2:DescribeKeyPairs",
                    "ec2:CreateKeyPair"
                ],
                "Resource": "*",
                "Condition": {
                    "DateGreaterThan": {
                        "aws:CurrentTime": "{{start_time}}"
                    },
                    "DateLessThanEquals": {
                        "aws:CurrentTime": "{{end_time}}"
                    }
                }
            }
        ]
    }
tm = Template(json.dumps(ec2_policy_meta_template))
parsed_policy = tm.render(region='us-east-1', ebs_volume_size='12', instance_type='t2.micro')
print(parsed_policy)

这是我在运行“template_utils.py”时遇到的错误

{"Version": "2012-10-17", "Statement": [{"Sid": "VisualEditor0", "Effect": "Allow", "Action": "ec2:RunInstances", "Resource": ["arn:aws:ec2:us-east-1::instance/*", "arn:aws:ec2:us-east-1::network-interface/*", "arn:aws:ec2:us-east-1::key-pair/*", "arn:aws:ec2:us-east-1::security-group/*", "arn:aws:ec2:us-east-1::subnet/*", "arn:aws:ec2:us-east-1::volume/*", "arn:aws:ec2:us-east-1::image/ami-*"], "Condition": {"ForAllValues:NumericLessThanEquals": {"ec2:VolumeSize": "12"}, "ForAllValues:StringEquals": {"ec2:InstanceType": "t2.micro"}}}, {"Sid": "VisualEditor1", "Effect": "Allow", "Action": ["ec2:TerminateInstances", "ec2:StartInstances", "ec2:StopInstances"], "Resource": "arn:aws:ec2:us-east-1::instance/*", "Condition": {"ForAllValues:StringEquals": {"ec2:InstanceType": "t2.micro"}}}, {"Sid": "VisualEditor2", "Effect": "Allow", "Action": ["ec2:Describe*", "ec2:GetConsole*", "cloudwatch:DescribeAlarms", "iam:ListInstanceProfiles", "cloudwatch:GetMetricStatistics", "ec2:DescribeKeyPairs", "ec2:CreateKeyPair"], "Resource": "*", "Condition": {"DateGreaterThan": {"aws:CurrentTime": ""}, "DateLessThanEquals": {"aws:CurrentTime": ""}}}]}
Traceback (most recent call last):
  File "/home/pranay/Desktop/work/template_utils.py", line 18, in <module>
    template_json = create_aws_iam_policy_template(
  File "/home/pranay/Desktop/work/template_utils.py", line 15, in create_aws_iam_policy_template
    template_json = meta_template_json.format(template_data)
KeyError: '"Version"'

【问题讨论】:

  • 如果你可以直接访问数据meta_template_name=meta_template.ec2_policy_meta_template,我不明白你为什么在meta_template_name="ec2_policy_meta_template"中使用字符串
  • 您使用JSONec2_policy_meta_template 转换为字符串,然后您将其与format() 一起使用-但format() 使用{ } 来识别变量,并且您拥有带有{"VERSION"... 的JSON 字符串format() 认为它是变量,它必须替换。而且你有更多的{},它将像替换值的地方一样。您必须使用{{ }} 来保持它们正常{ }
  • 我还看到您使用{{region}} 来放置一些值,但format() 不会放置它,因为它会将{{}} 视为正常字符串。它必须是{region}。似乎您将 format()jinja2 混合使用 {{ }} 在模板中放置元素。

标签: python python-3.x amazon-web-services boto3


【解决方案1】:

我认为你所有的问题是你混合了两种不同的方法来填充模板 - text.format()jinja2

text.format() 使用

  • {variable} 将值放入模板中
  • {{ }} 保持正常{ }

jinja2 使用

  • {{variable}} 将值放入模板中
  • { } 保持正常{ }

并且您有 {{region}} 来设置值,因此您可以使用 jinj2 方法,但您使用 format() 使用其他方法,它会在您的模板中看到 {"VERSION"... 并尝试替换它。

您必须使用jinja2 - 这会比为format() 更改模板更简单


string formatting

'{"VERSION": "{{region}}" }'.format(region="us-east2")

结果:

KeyError: '"VERSION"'

jinja2

from jinja2 import Template

t = Template('{"VERSION": "{{region}}" }')
t.render(region="us-east2")

结果:

'{"VERSION": "us-east2" }'

编辑:

看来你还是不明白。

jinja2 不是string 的功能,而是您必须安装的外部模块

 pip install Jinja2

并以特殊方式导入和使用。

对于您的示例,它可以是这样的

from jinja2 import Template

template_json = Template(meta_template_json).render(template_data)

它使用带有双 {{}} 的占位符 - 就像您的模板中的 {{region}}。当您有单个 { } 时,它不会尝试替换值,例如 '{"VERSION": ...}。所以它将以正确的方式与您的模板一起使用。

但原始 format() 以不同的方式工作 - 它使用单个 {} 的占位符 - 所以你有占位符 '{"VERSION": ...} 并且在 template_data 中找不到变量 "VERSION"替换它。它会产生问题。

【讨论】:

  • 我不要'{"VERSION": "us-east2" }',我只想填写占位符。休息将保持不变我根据您的建议对代码进行了一些更改,但我仍然不确定在我的函数中应该使用什么来代替 .format() 。我也对问题进行了更改。它完成了工作并给出了预期的结果,但出现了错误。 TIA。
  • 如果你想使用{{ region }},那么不要使用formatjinja2 - 你对{{ region }} 使用了错误的函数。如果您仍想使用format(),那么您必须使用{ region } 与单个{} 而不是双{{}}。但是那么您将不得不将所有原始 { } 替换为 {{, }}
  • 它抛出错误 AttributeError: 'str' object has no attribute 'jinja2' for line "template_json = meta_template_json.jinja2(template_data)"
  • 你看到我的回答了吗 - jinja2 不是字符串的功能,而是外部模块。您不能将其用作 meta_template_json.jinja2(template_data)" 您必须使用 import jinja2text = Template(meta_template_json).render(template_data)
  • 我用你的变量添加了例子。
猜你喜欢
  • 2018-01-28
  • 2018-07-17
  • 1970-01-01
  • 1970-01-01
  • 2013-06-23
  • 1970-01-01
  • 2015-03-08
  • 1970-01-01
  • 2010-11-08
相关资源
最近更新 更多