4

QSettings seems like a great thing in C++, it's essentially a flexible hash table where the key is a string and the value is a QVariant, so it can be quite a few types. However, in Python we already have this, its a dictionary. So I ask, what advantage would using QSettings in PyQt have over just using a dict?

Edit: More succinctly, every line that I'd use a QSettings object to assign a particular setting to a particular key, I could do the same thing with a dictionary. Yes, QSettings has some niceties like converting to an ini file but I can store a dict to file with the json module with the same number of lines of code. In terms of faculties provided by QSettings I'm trying to understand why people would use it over just using a dict and the json module, for instance. I've already perused the documentation to understand the things that QSettings offers, nothing stuck out to me as a really great feature so I'm basically asking, what do you view as the most beneficial features of QSettings and why is that superior to using a dict + json module

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Kevin S
  • 930
  • 10
  • 19
  • 1
    As the Documentation states they are not the same thing -- a Dictionary is in memory (RAM) and QSettings is stored on the harddrive and there in a nutshell is your main and most significant difference and based off this the list continues. – Dennis Jensen Aug 05 '19 at 13:46
  • 1
    if I have a dict that represents the settings I can easily use the json module to store the settings to a file. I realize QSettings has some options for storing the settings to an ini file. In terms of comparison I don't really think QSettings has an advantage here, I view them as equal for feature parity – Kevin S Aug 05 '19 at 14:23
  • @KevinS So what you might have asked is what is the difference between the JSON format (not the json module) and QSettings? – eyllanesc Aug 05 '19 at 14:28
  • @eyllanesc not necessarily. From an implementation perspective I know I need to store state of all widgets in memory and then to a file, then at another time I need to load the state from the file into memory and finally into the widget. It appears to me that QSettings is not superior to a python dict + json module. If in particular I know I'll have nested structures the QSetting module only supports ini files out of the box, anything else (such as yaml or json) and I'll have to supply the hooks to make it happen. This does not seem superior to just using a dict + json module – Kevin S Aug 05 '19 at 15:14
  • 1
    @KevinS As indicated in my answer the choice of one or another class depends specifically on your requirements, none is superior since they are only alternatives that replace the deficiencies of the other option. – eyllanesc Aug 05 '19 at 15:18
  • @eyllanesc sorry, yes to be clear one is superior but only if given the requirements. Of course I have not provided all of the requirements so I was really wondering in general the advantages of one strategy over the other. Still you've provided something in your answer that I had not considered and that is that QSettings has some additional support for specific Qt classes and typing information. – Kevin S Aug 05 '19 at 15:27

2 Answers2

3

From the Documentation

Users normally expect an application to remember its settings (window sizes and positions, options, etc.) across sessions. This information is often stored in the system registry on Windows, and in property list files on macOS and iOS. On Unix systems, in the absence of a standard, many applications (including the KDE applications) use INI text files.

QSettings is an abstraction around these technologies, enabling you to save and restore application settings in a portable manner. It also supports custom storage formats .

QSettings ‘s API is based on QVariant , allowing you to save most value-based types, such as QString , QRect , and QImage , with the minimum of effort.

So it is actually much more than a primitive dict object, it handles common tasks associated with saving the state of an application between restarts. It implements many convenient methods to achieve this.

Alex
  • 1,172
  • 11
  • 31
  • 90% or more of the methods listed on that page are related to interactions with a container. My concern is that in the same or less lines of code I could use a dict + json module and achieve the same concept (in memory storage easily stored to disk then reloaded) – Kevin S Aug 05 '19 at 14:31
  • You certainly could do that. This object seems like a convenient implementation of that which reduces the amount of work the developer needs to do. It may also be able to encode qt objects that the json module cannot out of the box. – Alex Aug 05 '19 at 14:47
  • That last line "may be able to encode qt objects that the json module cannot out of the box" is exactly the type of thing I'm hoping to find. It'd be nice if the QSettings module could know out of the box how to store all of the state on a widget just based on the widgets type, for instance. If such a capability existed it would easily win out over a dict+json – Kevin S Aug 05 '19 at 15:10
  • It is able to serialize most `QVariant` objects, which are simply value based objects. It is convenient to read them back and use them for configuring a widget on statrup. See this [example](https://doc.qt.io/qtforpython/PySide2/QtCore/QSettings.html#restoring-the-state-of-a-gui-application). There is nothing in the documentation that indicates you can save all the attributes of an arbitrary widget directly, however. You would still need to save and reload the specific attributes of that widget and pass them to the constructor on startup again. – Alex Aug 05 '19 at 15:21
3

QSettings is not a container, so in python it is not equivalent to a dictionary. Something similar to a dictionary in Qt/C++ is perhaps QMap (obviously with its limitations).

QSettings is a class that allows you to permanently save information, that is, when the application is reopened then even that information is accessible unlike a dictionary that when the application is closed loses the information it saved.

For example, let's use the following examples and run it several times:

Dictionary:

d = {"foo": "bar"}
print(d)
# modify dictionary
d["foo"] = "rab"

Output:

{'foo': 'bar'}
{'foo': 'bar'}
{'foo': 'bar'}
{'foo': 'bar'}
{'foo': 'bar'}

QSettings:

from PyQt5 import QtCore

settings = QtCore.QSettings("Foo", "Bar")
value = settings.value("value", 0, type=int)
print(value)
settings.setValue("value", value + 1)
settings.sync()

Output:

0
1
2
3
4

In the first case it does not take into account the previous execution of the program but in the second case it does.

In conclusion, QSettings allows you to save information that your application can use when running again, such as saving sessions, permissions, etc.

In addition, QSettings is an abstraction layer that implements the previous functionality on several platforms.


According to the edition you indicate, I think you want to compare QSettings with dict + json module.

Well, the choice depends on the user but the following could help you choose:

  • QSettings supports storing many native Qt classes such as QSize, QPoint, etc. however with Json it does not support them.

So at the end of all QSettings is an option, unique in the world of Qt, but not unique in the world of Python since there are others like PyYAML(YAML), ConfigParser(INI), xml.etree.ElementTree(XML), etc.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • I would argue that it is still a container but a container that saves and reads from a file. When QSettings is updated it saves its settings to a file and when the program restarts, QSettings reads from a file to initialize itself. While in memory it acts as a hash table (if you look at the source code QSettings is a C++ Map). – Error - Syntactical Remorse Aug 05 '19 at 14:04
  • @Error-SyntacticalRemorse Is that container can have many definitions depending on exactly what is being talked about, for example check https://stackoverflow.com/questions/11575925/what-exactly-are-containers-in-python-and-what-are-all-the-python-container and http://www.cplusplus.com/reference/stl/ – eyllanesc Aug 05 '19 at 14:08
  • A C++ Map is a container object based on the definitions provided by both of those links. Though it is not a `Collections.abc.Container`. If you want to dive into it with that extent than a normal `dict` is not a Container in CPython. – Error - Syntactical Remorse Aug 05 '19 at 14:09
  • @Error-SyntacticalRemorse QSettings can be a container but I think that strictly speaking you must have an internal container that stores the information until it is stored in persistent memory. If we only go to the linguistic definition then every class that has a container would also be a container. – eyllanesc Aug 05 '19 at 14:11
  • @Error-SyntacticalRemorse That is exactly what I mean, it is a philosophical discussion, from the point of view of where you see it, an object may or may not be a container, but my initial argument of my answer only points to a dictionary-like class (QMap) but IMHO The most important thing is in my example since there you can clearly see the difference between the dict and QSettings. – eyllanesc Aug 05 '19 at 14:13
  • I wasn't inferring. QSettings is a container (technically a cache) that runs in memory while the program is running. The [source code](https://code.woboq.org/qt5/qtbase/src/corelib/io/qsettings.cpp.html) shows QSettings is a C++ Map object which is the C++ equivalent to a python dict. – Error - Syntactical Remorse Aug 05 '19 at 14:14
  • @Error-SyntacticalRemorse In order not to extend the discussion I have crossed out that part if you consider that it can bring confusion :-) – eyllanesc Aug 05 '19 at 14:17
  • 1
    your edit has gotten at the cusp of the issue and I appreciate this insight "QSettings supports storing many native Qt classes such as QSize, QPoint, etc. however with Json it does not support them." This is a good point. – Kevin S Aug 05 '19 at 15:19