I want to use a .py file like a config file.
So using the {...}
notation I can create a dictionary using strings as keys but the definition order is lost in a standard python dictionary.
My question: is it possible to override the {...}
notation so that I get an OrderedDict()
instead of a dict()
?
I was hoping that simply overriding dict constructor with OrderedDict (dict = OrderedDict
) would work, but it doesn't.
Eg:
dict = OrderedDict
dictname = {
'B key': 'value1',
'A key': 'value2',
'C key': 'value3'
}
print dictname.items()
Output:
[('B key', 'value1'), ('A key', 'value2'), ('C key', 'value3')]
OrderedDict
is not "standard python syntax", however, an ordered set of key-value pairs (in standard python syntax) is simply:To explicitly get an
OrderedDict
:Another alternative, is to sort
dictname.items()
, if that's all you need:What you are asking for is impossible, but if a config file in JSON syntax is sufficient you can do something similar with the
json
module:If what you are looking for is a way to get easy-to-use initialization syntax - consider creating a subclass of OrderedDict and adding operators to it that update the dict, for example:
d will be- OrderedMap([(1, 2), (4, 3), ('key','value')])
Another possible syntactic-sugar example using the slicing syntax:
To literally get what you are asking for, you have to fiddle with the syntax tree of your file. I don't think it is advisable to do so, but I couldn't resist the temptation to try. So here we go.
First, we create a module with a function
my_execfile()
that works like the built-inexecfile()
, except that all occurrences of dictionary displays, e.g.{3: 4, "a": 2}
are replaced by explicit calls to thedict()
constructor, e.g.dict([(3, 4), ('a', 2)])
. (Of course we could directly replace them by calls tocollections.OrderedDict()
, but we don't want to be too intrusive.) Here's the code:With this modification in place, we can modify the behaviour of dictionary displays by overwriting
dict
. Here is an example:Now we can run this file using
my_execfile("test.py")
, yielding the outputNote that for simplicity, the above code doesn't touch dictionary comprehensions, which should be transformed to generator expressions passed to the
dict()
constructor. You'd need to add avisit_DictComp()
method to theDictDisplayTransformer
class. Given the above example code, this should be straight-forward.Again, I don't recommend this kind of messing around with the language semantics. Did you have a look into the
ConfigParser
module?The one solution I found is to patch python itself, making the
dict
object remember the order of insertion.This then works for all kind of syntaxes:
etc.
I have taken the
ordereddict
C implementation from https://pypi.python.org/pypi/ruamel.ordereddict/ and merged back into the main python code.If you do not mind re-building the python interpreter, here is a patch for Python 2.7.8: https://github.com/fwyzard/cpython/compare/2.7.8...ordereddict-2.7.8.diff .A
As of python 3.6, all dictionaries will be ordered by default. For now, this is an implementation detail of
dict
and should not be relied upon, but it will likely become standard after v3.6.Insertion order is always preserved in the new
dict
implementation:As of python 3.6
**kwargs
order [PEP468] and class attribute order [PEP520] are preserved. The new compact, ordered dictionary implementation is used to implement the ordering for both of these.