【问题标题】:Use different config files - decision should be made via command-line argument使用不同的配置文件 - 应通过命令行参数做出决定
【发布时间】:2014-11-04 07:22:02
【问题描述】:

我有一个脚本,它使用一个名为 config.py 的配置文件。实际上,这是一个配置模块。无论如何:配置模块包含很多参数和字典以及字典列表等。

在今天的脚本中是这样使用的

import config

def main(): 
    myParameter = config.myParameter

现在我有这个脚本的另一个应用场景,它使用了相关的配置('config_advanced.py',但是参数和字典有不同的值。

我现在的目标是,选择使用的配置模块的名称作为传递的命令行参数:

myScript.py -configuration config_advanced.py

由于配置模块与主脚本位于同一文件夹中,我想我必须先将传递的配置文件重命名为“config.py”。之后我可以执行import config。否则,如果我使用 `import config_advanced,我将无法使用像

这样的调用
config.myParameter

在主脚本中。

另一种可能是将配置模块放在子文件夹中并保留名称 config.py。传递的命令行参数必须包含子文件夹。

无论哪种方式,我都无法在主文件的顶部执行导入,因为我必须先进行参数解析。这不是技术问题,但有人说这至少是不好的做法。

你怎么看? 有什么更好的方法来不费吹灰之力地做到这一点? 非常感谢


编辑:
一种可行的解决方案是

import sys fullpath = "d:\\python\\scripts\\projectA\\configurationFiles\\" 
sys.path.append(fullpath) 
config = __import__('config_advanced')


如果没有 syspath,它就不起作用,所以下面的尝试将不起作用:

config = __import__('d:\\python\\scripts\\projectA\\configurationFiles\\config_advanced')
config = __import__('d:\\python\\scripts\\projectA\\configurationFiles\\config_advanced.py')

【问题讨论】:

  • 必须是python吗?使用 Json/yaml/ini 会更容易(也更安全)。
  • 您可以使用内置的__import__()函数按名称导入模块并将结果命名为config
  • 非常感谢。有效!我必须先附加配置文件的路径。或者还有其他方法吗?这是我的解决方案:import sysfullpath = "d:\\python\\scripts\\projectA\\configurationFiles\\"sys.path.append(fullpath)config = __import__('config_advanced')
  • 抱歉格式错误。根据帮助两个空格应该添加一个换行符:“用两个空格结束一行以添加一个
    换行符”。但我想,我在这里做错了
  • cmets 中的代码很难阅读,而且无法正确缩进,所以将其编辑到您的问题中。 cmets 中的代码应仅限于微小的片段。

标签: python configuration arguments


【解决方案1】:

另一种可能与您在问题中的建议类似,但不需要您将内容隐藏在子文件夹中,是将 config_advanced.py 和 config_plain.py 放在与主脚本相同的文件夹中,然后动态制作config.py 指向您要使用的实际配置文件的链接。

不过,martineau 的建议要简单得多

OTOH,georg 提出了一个非常有效的观点,尤其是如果这个脚本不只是供您个人使用。虽然使用 Python 本身来处理配置数据既灵活又强大,但它可能有点强大了。配置数据应该只是数据,而不是实时可执行代码。如果您在修改配置数据时犯了一个小错误,如果它位于可执行文件中,则可能会造成严重破坏。如果恶意用户接触到它,他们可能造成的损害是无限的。

一个普通的旧数据文件中的错误数据最坏的情况是会导致 ValueError,如果它做了一些你的配置解析代码没有怀疑的奇怪事情。但是实时 Python 文件中的不良数据可能会引发各种令人讨厌的错误。或者更糟糕的是,它可以在完全沉默的情况下做一些坏事……


回复你的cmets,这里有一些代码来说明第一点:

#! /usr/bin/env python

import os

config_file = "config.py"

def link_config(mode):
    if os.path.exists(config_file):
        os.remove(config_file)

    config_name = "config_%s.py" % mode
    os.symlink(config_name, config_file)

#.... parse command line to determine config_mode string, then do
link_config(config_mode)

#Now import the newly-linked config file
import config

如果 config_mode == "plain" 上述代码将导致 config_plain.py 被导入为 'config'

如果 config_mode == "advanced" 会导致 config_advanced.py 被导入为 'config'

但正如我之前所说,martineau 的方法要简单得多。而 IIRC,os.symlink 可能无法在非 unix 系统上运行。

...

至于你的第二点,请查看the docs for the json module

【讨论】:

  • 1.我不明白第一点 ;) - 你的意思是,我应该先将文件写入 config.py,以便 config.py 包含类似“import config_plain”的内容,然后再导入配置?
  • 2.配置应该只包含数据:对我来说似乎有效:) 我不确定字典列表的处理,我认为使用 python-modul 作为配置将是最简单的方法。我以前从未使用过 json,但它似乎与普通的 python 字典非常相似。无论如何:在配置中仅使用数据意味着我需要一些解析。所以我想我应该使用 config-parser 模块?但是如何使用 config-parser 读取带有列表的 json 格式的字典列表呢?有什么例子吗?
  • 非常感谢您的澄清。我以前从未见过 os.symlink。但我理解你的意思,它可能行不通。所以我实施了martineau的方法。我希望我做对了:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-06
  • 1970-01-01
  • 2020-02-26
相关资源
最近更新 更多