Python:带字符串插值的动态json

2024-09-29 19:22:05 发布

您现在位置:Python中文网/ 问答频道 /正文

我创建了一类提供一些云基础设施的函数

response = self.ecs_client.register_task_definition(
containerDefinitions=[
                {
                    "name": "redis-283C462837EF23AA",
                    "image": "redis:3.2.7",
                    "cpu": 1,
                    "memory": 512,
                    "essential": True,
                },
...

这是一个很长的json,我只展示了一个开始

然后我重构了代码,使用一个参数,而不是硬编码的散列、内存和cpu

response = self.ecs_client.register_task_definition(
containerDefinitions=[
                {
                    "name": f"redis-{git_hash}",
                    "image": "redis:3.2.7",
                    "cpu": {num_cpu},
                    "memory": {memory_size},
                    "essential": True,
                },
...

在此代码之前,我从配置文件中读取了git_hashnum_cpumemory_size的值

现在,我还想从一个文件中读取整个json

问题是,如果我将{num_cpu}等保存在文件中,字符串插值将不起作用

如何从逻辑中提取json,并且仍然使用字符串插值或变量


Tags: nameimageselfredisclientregisterjsontask
1条回答
网友
1楼 · 发布于 2024-09-29 19:22:05

您可以从string使用Template

{
    "name": "redis-${git_hash}",
    "image": "redis:3.2.7",
    "cpu": ${num_cpu},
    "memory": ${memory_size},
    "essential": true
}
from string import Template
import json

if __name__ == '__main__':
    data = dict(
        num_cpu = 1, 
        memory_size = 1,
        git_hash = 1
    )
    with open('test.json', 'r') as json_file:
        content = ''.join(json_file.readlines())
        template = Template(content)
        configuration = json.loads(template.substitute(data))
        print(configuration)

# {'name': 'redis-1', 'image': 'redis:3.2.7', 'cpu': 1, 'memory': 1, 'essential': True}

观点:我认为总体方法是错误的。这种方法不如其他方法流行是有原因的。您可以将配置分为两个文件(1)静态选项列表和(2)紧凑的可变配置,并在代码中组合它们

编辑:您可以创建一个对象,该对象从标准(静态或可变)JSON文件FileConfig读取配置。然后用另一个对象,行ComposedConfig合成它们

这将允许您扩展行为,例如,在混合中添加运行时配置。通过这种方式,JSON文件中的配置不再依赖于运行时参数,您可以将系统中的可更改内容与静态内容区分开来

PS:get方法只是解释组合行为的一个示例;您可以使用其他方法/设计

import json
from abc import ABC, abstractmethod 


class Configuration(ABC):
    
    @abstractmethod
    def get(self, key: str, default: str) -> str:
        pass


class FileConfig(Configuration):

    def __init__(self, file_path):
        self.__content = {}
        with open(file_path, 'r') as json_file:
            self.__content = json.load(json_file)
            
    def get(self, key: str, default: str) -> str:
        return self.__content.get(key, default)


class RunTimeConfig(Configuration):
    def __init__(self, option: str):
        self.__content = {'option': option}
    
    def get(self, key: str, default: str) -> str:
        return self.__content.get(key, default)


class ComposedConfig:

    def __init__(self, first: Configuration, second: Configuration):
        self.__first = first
        self.__second = second

    def get(self, key: str, default: str) -> str:
        return self.__first.get(key, self.__second.get(key, default))


if __name__ == '__main__':
    static = FileConfig("static.json")
    changeable = FileConfig("changeable.json")
    runTime = RunTimeConfig(option="a")
    config = ComposedConfig(static, changeable)
    alternative = ComposedConfig(static, runTime)
    print(config.get("image", "test")) # redis:3.2.7
    print(alternative.get("option", "test")) # a

相关问题 更多 >

    热门问题