How to allow a many-to-many relationship to be configured in Python
I have a simple app which requires a many-to-many relationship to be configured as part of its set-up. For example, the app requires a list of repository URLs, a list of users and for each user, a subset of the repository URLs.
I first thought of using a config.py
file similar to the following:
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']
}
which I could import. But this is quite messy as the config file lives outside my python-path and I would rather use a standard configuration approach such as using ini files or YAML.
Is there an elegant way of configuring a relationship such as this without importing a Python directly?
I would store the config in JSON format. For example:
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
If you like the idea of representing structure by indentation (like in Python) then YAML will be perfect for you. If you don't want to rely on whitespace and prefer explicit syntax then better go with JSON. Both are easy to understand and popular, which means that there are Python libraries out there.
Additional advantage is the fact that, in contrast to using standard Python code, you can be sure that your configuration file can contains only data and no arbitrary code that will get executed.
The tactic I use is to put the whole application in a class, and then instead of having an importable config file, allow the user to pass in configuration to the constructor. Or, in more complicated cases they could even subclass the application class to add members or change behaviours. Although this does require a little knowledge of Python syntax in order to configure the app, it's not really that difficult, and much more flexible than the ini/markup config file approach.
So you example you could have an invoke-script outside the pythonpath looking like:
#!/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()
Then to have a second configuration they can swap out or even run at the same time, you simply cope the invoke-script and change the settings in it.
精彩评论