代码之家  ›  专栏  ›  技术社区  ›  DavidWinterbottom

如何允许在python中配置多对多关系

  •  2
  • DavidWinterbottom  · 技术社区  · 15 年前

    我有一个简单的应用程序,它需要将多对多关系配置为其设置的一部分。例如,应用程序需要一个存储库URL列表、一个用户列表以及每个用户的存储库URL子集。

    我第一次想到使用 config.py 类似于以下内容的文件:

    repositories = {
        'repo1': 'http://svn.example.com/repo1/',
        'repo2': 'http://svn.example.com/repo2/',
        'repo3': 'http://svn.example.com/repo3/',
    }
    user_repository_mapping = {
        'person_A': ['repo1', 'repo3'],
        'person_B': ['repo2'],
        'person_C': ['repo1', 'repo2']
    }
    

    我可以进口。但这相当混乱,因为配置文件位于我的python路径之外,我宁愿使用标准配置方法,如使用ini文件或yaml。

    在不直接导入Python的情况下,是否有一种优雅的方式来配置这种关系?

    3 回复  |  直到 15 年前
        1
  •  2
  •   John Keyes    15 年前

    我将以JSON格式存储配置。例如:

    cfg = """
    {
        "repositories": {
            "repo1": "http://svn.example.com/repo1/",
            "repo2": "http://svn.example.com/repo2/",
            "repo3": "http://svn.example.com/repo3/"
        },
        "user_repository_mapping": {
            "person_A": ["repo1", "repo3"],
            "person_B": ["repo2"],
            "person_C": ["repo1", "repo2"]
        }
    }
    """
    
    import simplejson as json
    config = json.loads(cfg)
    person = "person_A"
    repos = [config['repositories'][r] for r in config['user_repository_mapping'][person]]
    print repos
    
        2
  •  1
  •   Adam Byrtek    15 年前

    如果您喜欢用缩进(如在Python中)表示结构的想法,那么Yaml将是您的完美选择。如果您不想依赖空白并且更喜欢显式语法,那么最好使用JSON。两者都很容易理解和流行,这意味着那里有Python库。

    另一个优点是,与使用标准的python代码相比,您可以确保配置文件只包含数据,不包含将要执行的任意代码。

        3
  •  -1
  •   bobince    15 年前

    我使用的策略是将整个应用程序放在一个类中,然后允许用户将配置传递给构造函数,而不是具有可导入的配置文件。或者,在更复杂的情况下,它们甚至可以对应用程序类进行子类化,以添加成员或更改行为。尽管这需要对Python语法有一点了解才能配置应用程序,但它并没有那么困难,而且比ini/markup config文件方法灵活得多。

    因此,举例来说,您可以在pythonpath之外有一个invoke脚本,如下所示:

    #!/usr/bin/env python
    
    import someapplication
    
    class MySomeApplication(someapplication.Application):
        repositories = {
           'repo1': 'http://svn.example.com/repo1/',
           'repo2': 'http://svn.example.com/repo2/',
           'repo3': 'http://svn.example.com/repo3/',
        }
        user_repository_mapping = {
            'person_A': ['repo1', 'repo3'],
            'person_B': ['repo2'],
            'person_C': ['repo1', 'repo2']
        }
    
    MySomeApplication().run()
    

    然后,为了获得第二个配置,它们可以交换,甚至可以同时运行,只需处理调用脚本并更改其中的设置。