Saving and Restoring Application Settings with QSettings in PyQt6

Learn how to use QSettings to remember user preferences, window sizes, and configuration options between sessions
Heads up! You've already completed this tutorial.

Most desktop applications need to remember things between sessions. Maybe your user picked a dark theme, resized the window, or toggled a feature on or off. Without a way to save those choices, your app would forget everything the moment it closes. That's where QSettings comes in.

QSettings is a class provided by Qt (and available through PyQt6) that gives you a simple, cross-platform way to store and retrieve application settings. It handles all the platform-specific details for you — on Windows it uses the registry, on macOS it uses property list files, and on Linux it uses configuration files. You just read and write values, and Qt figures out the rest.

In this tutorial, we'll walk through everything you need to know to start using QSettings effectively in your PyQt6 applications.

Creating a QSettings Object

To use QSettings, you first need to create an instance. The most common way is to pass in your organization name and application name:

python
from PyQt6.QtCore import QSettings

settings = QSettings('MyCompany', 'MyApp')

These two strings — the organization name and the application name — are used by Qt to determine where your settings are stored. They act like a namespace, keeping your app's settings separate from every other application on the system.

You can check exactly where your settings file lives by printing the file path:

python
print(settings.fileName())

On Linux, this might print something like:

python
/home/username/.config/MyCompany/MyApp.conf

On Windows, it would point to a registry path, and on macOS, a .plist file. You don't need to worry about these differences — QSettings handles it for you.

Storing Values

Saving a setting is as simple as calling setValue() with a key and a value:

python
settings.setValue('theme', 'Dark')
settings.setValue('font_size', 14)
settings.setValue('show_toolbar', True)

The key is a string that you'll use later to retrieve the value. The value can be a string, integer, boolean, list, or other common Python types. QSettings will serialize it appropriately.

That's it — the value is saved. When you call setValue(), the data is written to persistent storage (the exact timing depends on the platform, but it happens automatically).

Reading Values Back

To read a setting, use value():

python
theme = settings.value('theme')
print(theme)  # 'Dark'

If the key doesn't exist (for example, the very first time your app runs), value() returns None by default. You can provide a default value as the second argument:

python
theme = settings.value('theme', 'Light')

Now if there's no theme key stored yet, you'll get 'Light' instead of None.

Handling Types

One thing that catches people off guard: QSettings stores everything as strings internally (at least when using INI-style backends on Linux). This means that when you read back a number or boolean, you might get a string instead of the type you expected.

To handle this, you can pass the type parameter:

python
font_size = settings.value('font_size', 14, type=int)
show_toolbar = settings.value('show_toolbar', True, type=bool)

By specifying type=int or type=bool, you ensure that the returned value is the correct Python type, regardless of how it was stored internally. This is especially important for booleans — without the type parameter, you might get the string 'true' instead of the boolean True.

Checking if a Setting Exists

Before reading a value, you might want to check whether it has been set at all. Use contains():

python
if settings.contains('theme'):
    theme = settings.value('theme')
    print(f'Found saved theme: {theme}')
else:
    print('No theme saved yet, using default')
    settings.setValue('theme', 'Light')
    theme = 'Light'

This pattern is useful when you want to distinguish between "the user explicitly set this value" and "this is just the default."

A Complete Example

Let's put this all together in a small PyQt6 application that remembers the window size and position, as well as a user-selected theme. When you close the app, it saves these settings. When you reopen it, everything is restored.

python
import sys
from PyQt6.QtWidgets import (
    QApplication, QMainWindow, QComboBox,
    QVBoxLayout, QWidget, QLabel
)
from PyQt6.QtCore import QSettings, QSize, QPoint


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.settings = QSettings('MyCompany', 'MyApp')

        self.setWindowTitle("QSettings Demo")

        # Create a simple UI with a theme selector
        layout = QVBoxLayout()

        layout.addWidget(QLabel("Choose a theme:"))

        self.theme_combo = QComboBox()
        self.theme_combo.addItems(['Light', 'Dark', 'Blue'])
        layout.addWidget(self.theme_combo)

        container = QWidget()
        container.setLayout(layout)
        self.setCentralWidget(container)

        # Restore settings
        self.load_settings()

    def load_settings(self):
        # Restore window size and position
        size = self.settings.value('window_size', QSize(400, 300))
        position = self.settings.value('window_position', QPoint(100, 100))
        self.resize(size)
        self.move(position)

        # Restore theme selection
        theme = self.settings.value('theme', 'Light')
        index = self.theme_combo.findText(theme)
        if index >= 0:
            self.theme_combo.setCurrentIndex(index)

    def save_settings(self):
        self.settings.setValue('window_size', self.size())
        self.settings.setValue('window_position', self.pos())
        self.settings.setValue('theme', self.theme_combo.currentText())

    def closeEvent(self, event):
        self.save_settings()
        super().closeEvent(event)


app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec()

Run this app, move or resize the window, select a different theme from the dropdown, then close the app. When you run it again, the window should appear in the same position and size, with the same theme selected.

Let's walk through what's happening:

  • In __init__, we create a QSettings object with our organization and app names.
  • load_settings() reads values from persistent storage and applies them to the window and widgets. Notice how we pass default values (QSize(400, 300), QPoint(100, 100), 'Light') so the app has sensible starting values on the very first run.
  • save_settings() writes the current window size, position, and theme to settings.
  • closeEvent() is a built-in Qt method that gets called when the window is about to close. We override it to save our settings right before that happens.

Removing Settings

If you need to delete a stored setting, use remove():

python
settings.remove('theme')

This removes the theme key entirely. After this, settings.contains('theme') would return False.

Listing All Keys

To see everything that's currently stored, use allKeys():

python
keys = settings.allKeys()
print(keys)  # ['theme', 'font_size', 'show_toolbar', ...]

This can be handy for debugging, or if you want to iterate over all settings to display them in a preferences dialog.

Organizing Settings with Groups

As your app grows, you might end up with a lot of settings. QSettings supports groups, which let you organize keys into sections — similar to folders:

python
settings.beginGroup('appearance')
settings.setValue('theme', 'Dark')
settings.setValue('font_size', 14)
settings.endGroup()

settings.beginGroup('network')
settings.setValue('timeout', 30)
settings.setValue('retry_count', 3)
settings.endGroup()

When you read them back, you use the same group:

python
settings.beginGroup('appearance')
theme = settings.value('theme', 'Light')
settings.endGroup()

Alternatively, you can use a / separator in the key name as a shorthand:

python
settings.setValue('appearance/theme', 'Dark')
theme = settings.value('appearance/theme', 'Light')

Both approaches produce the same result. The slash syntax is a bit more concise, while beginGroup()/endGroup() is cleaner when you're reading or writing several settings in the same group at once.

Using QSettings with setOrganizationName and setApplicationName

Instead of passing the organization and app names every time you create a QSettings object, you can set them once on the QApplication:

python
app = QApplication(sys.argv)
app.setOrganizationName('MyCompany')
app.setApplicationName('MyApp')

After this, you can create QSettings objects without any arguments:

python
settings = QSettings()

It will automatically use the organization and application names you set. This is especially convenient in larger applications where you create QSettings in multiple places — you only need to define the names once at startup.

Managing Many Settings with a Dictionary

If your application has a lot of settings, checking each one individually can get repetitive. A cleaner approach is to define your defaults in a dictionary and loop through them:

python
DEFAULTS = {
    'theme': 'Light',
    'font_size': 14,
    'show_toolbar': True,
    'language': 'English',
    'auto_save': True,
    'auto_save_interval': 5,
}

settings = QSettings('MyCompany', 'MyApp')

# Load settings with defaults
config = {}
for key, default in DEFAULTS.items():
    config[key] = settings.value(key, default, type=type(default))

print(config)

By using type=type(default), each value is automatically cast to the same type as its default. This keeps everything tidy and makes it easy to add new settings later — just add another entry to the dictionary.

Where Are Settings Stored?

If you're curious about where QSettings puts your data, or if you need to find the settings file for debugging, here's a quick summary:

Platform Storage Location
Windows Registry under HKEY_CURRENT_USER\Software\MyCompany\MyApp
macOS ~/Library/Preferences/com.mycompany.MyApp.plist
Linux ~/.config/MyCompany/MyApp.conf

You can always check the exact path using:

python
print(settings.fileName())

On Linux and macOS, the settings file is a plain text file that you can open and inspect directly, which is helpful for debugging.

Working with QStandardPaths

QSettings tells you where settings are stored, but sometimes you need to know about other standard locations — where to store cached data, application data, or downloaded files. Qt provides QStandardPaths for this:

python
from PyQt6.QtCore import QStandardPaths

# Where to store app configuration
config_path = QStandardPaths.writableLocation(QStandardPaths.AppConfigLocation)
print(f'Config: {config_path}')

# Where to store app data
data_path = QStandardPaths.writableLocation(QStandardPaths.AppDataLocation)
print(f'Data: {data_path}')

# Where to store cached files
cache_path = QStandardPaths.writableLocation(QStandardPaths.CacheLocation)
print(f'Cache: {cache_path}')

QStandardPaths is separate from QSettings, but they complement each other well. Use QSettings for simple key-value preferences, and QStandardPaths when you need to store actual files (databases, logs, downloaded content) in the right platform-appropriate location.

Summary

QSettings gives you a clean, cross-platform way to persist user preferences in your PyQt6 applications. Here's a quick recap of the essentials:

  • Create a QSettings object with your organization and app name.
  • Use setValue(key, value) to save a setting.
  • Use value(key, default, type=...) to read a setting, with a default fallback and explicit type.
  • Use contains(key) to check if a setting exists.
  • Use remove(key) to delete a setting.
  • Override closeEvent() on your main window to save settings when the app closes.
  • Organize related settings with groups using beginGroup()/endGroup() or / in key names.

Once you're comfortable with these basics, you'll find that QSettings quietly handles one of those essential-but-tedious parts of desktop app development — letting you focus on the interesting stuff.

Well done, you've finished this tutorial! Mark As Complete
[[ user.completed.length ]] completed [[ user.streak+1 ]] day streak

PyQt/PySide 1:1 Coaching with Martin Fitzpatrick

Save yourself time and frustration. Get one on one help with your Python GUI projects. Working together with you I'll identify issues and suggest fixes, from bugs and usability to architecture and maintainability.

Book Now 60 mins ($195)

Martin Fitzpatrick

Saving and Restoring Application Settings with QSettings in PyQt6 was written by Martin Fitzpatrick.

Martin Fitzpatrick has been developing Python/Qt apps for 8 years. Building desktop applications to make data-analysis tools more user-friendly, Python was the obvious choice. Starting with Tk, later moving to wxWidgets and finally adopting PyQt. Martin founded PythonGUIs to provide easy to follow GUI programming tutorials to the Python community. He has written a number of popular Python books on the subject.