【问题标题】:Design for dealing with configuration files处理配置文件的设计
【发布时间】:2018-03-05 00:53:41
【问题描述】:

我正在编写代码,需要打开一个 JSON 文件,该文件包含与软件使用相关的一般配置,将其解析为 dict 并可能覆盖其某些值。这些配置需要在运行时多次访问以检查设置。

例如:其中一个配置是“用户名”和“密码”,如果不存在则需要用户填写,否则直接读取。另一个配置与“软件应该如何工作”有关,可能有“模式 A”、“模式 B”和“模式 C”的值。

问题是:我不是程序员,我想不出一个好的设计来管理配置。我应该打开 JSON 文件,每次需要时重写并保存它,还是将其解析为一个变量并将该变量保存在内存中,直到我不再需要它(就在代码完成运行之前),然后将其保存到最后的 JSON 文件?

另一个问题是:如果我更喜欢将其解析为变量并保留到程序结束,我应该怎么做?这个变量需要被几个函数访问,所以我认为我应该使用一个全局变量,但我读过使用“全局”语句写入全局变量是一种不好的做法,可能会导致混乱。示例:

import json
config_global = None

def read_JSON_file():
    config_file = open(r'config_file.json')
    global config_global
    config_global = json.load(config_file)
    config_file.close()

def functionA():
    global config_global
    # Do something with config_global

def functionB():
    global config_global
    # Do something with config_global

def save_JSON_file()
    config_file = open(r'config_file.json', 'w')
    json.dump(config_global, config_file)
    config_file.close()

read_JSON_file()
functionA()
functionB()
save_JSON_file()

我还认为我可以在函数调用之间传递配置变量引用,但我不知道这是否是一个好的解决方案,因为我必须为每个函数传递它,每次:

import json

def read_JSON_file() -> dict:
    config_file = open(r'config_file.json')
    config = json.load(config_file)
    config_file.close()
    return config

def functionA(config: dict):
    # Do something with config

def functionB(config: dict):
    # Do something with config

def save_JSON_file(config: dict)
    config_file = open(r'config_file.json', 'w')
    json.dump(config, config_file)
    config_file.close()

parsed_config = read_JSON_file()
functionA(parsed_config)
functionB(parsed_config)
save_JSON_file(parsed_config)

我还阅读了与使用单例相关的内容,但我不完全了解它是如何工作的,或者它是否是一个好的解决方案。

最终,我想知道什么是解决这个问题的好方法。请向我展示我在实施过程中可能遇到的问题,并随意提出更好的解决方案。

感谢您的关注和帮助。

【问题讨论】:

  • 我是一名程序员,我想不出一个好的设计来管理配置。

标签: python json configuration


【解决方案1】:

我会将配置设为一个模块,它可以是 imported 的全部或部分,也可以是任何其他需要它的脚本。模块本质上是单例的,并在首次加载时缓存在sys.modules 中,如果随后尝试重新import 它,将使用该条目 - 因此它不会产生每次实际读取和执行的开销发生这种情况。

在配置模块的主体中​​,可以打开并加载json文件中的信息。可以通过多种方式提供此信息。一种是简单的字典(可能只是 json.load() 返回的任何内容。另一种是解析和转换它并创建与它的各个部分相对应的模块属性。

当然,您也可以在模块中添加任何您想要的功能。例如,您可能需要一个特殊函数,该函数必须在其包含的值可用之前调用,而不是在首次导入时自动执行。

换句话说,这将是一种非常灵活的方式来处理问题并允许大量自定义,因为它是可扩展的。

【讨论】:

  • 好的,所以我会有一个新模块,它包含一个名为“config_global”的全局变量,它的值是 json.load() 返回的字典的值,对吧?然后,当我需要访问配置时,我会导入这个新模块并获取它的“config_global”变量。但是如果我需要覆盖 config_global 变量中的配置,我不会写一个全局变量(即使它在其他模块中)?
  • 您可以 from config import config_global 假设您将模块命名为 config.py 并且它定义了一个名为 config_global 的模块级变量(通过读取 json 文件填充)。如果您更改 config_global 的内容,它们将保留在内存中,并被拥有(或将要)也拥有 import 的任何其他脚本看到。您可以向模块添加一个函数,该函数将当前内容写回原始文件或其他文件——这一切都取决于您将使用什么以及如何使用它,因为您可以定义 API 来使用它看合适。
  • 好的,我明白了,这似乎是一个很好的解决方案,但我还有一个问题:在“config.py”模块中,“config_global”是一个全局(模块级)变量。因此,如果我在第一次填充它以读取 json 文件或在运行时更改某些配置时写入它,我本质上是在写入全局。难道它不会仍然被认为是一种不好的做法(因为写入全局通常被认为是一种不好的做法)?
  • 它是一个模块级别的全局变量,与其他语言中通常称为的全局变量略有不同(并且不那么繁琐)。如果您甚至担心在外部模块中使用 on,您可以提供函数来获取和设置其中的值,而不是直接在 import 它的脚本中对其进行更改。将您的 config.py 模块视为定义模块对象的单个实例(实际上就是这样)。像任何类一样,您可以提供“getter”和“setter”来控制对实例内部的访问(或不访问)。在 Python 中,提供它们是很常见的
猜你喜欢
  • 1970-01-01
  • 2015-01-17
  • 1970-01-01
  • 2011-08-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-08
  • 1970-01-01
相关资源
最近更新 更多