When you're setting a window icon or adding icons to buttons in your PySide6 application, you need to pass a file path to QIcon. If the icon file isn't being found, you might be tempted to use a full absolute path to make sure Python can locate it. That can work during development, but there are a few common pitfalls with how you build that path — and some good reasons to consider alternatives.
In this article, we'll look at how to correctly construct absolute file paths for QIcon, and then explore why relative paths (built dynamically) are almost always a better approach.
Building paths by joining strings
You might start by trying something like this:
self.setWindowIcon(QIcon("D://abc/" + "resource/logo.ico"))
This can work, but manually concatenating strings to build file paths is fragile. Different operating systems use different path separators (\ on Windows, / on Linux and macOS), and it's easy to end up with doubled separators, missing separators, or paths that only work on your machine.
Python gives us better tools for this.
Using os.path.join
The os.path.join function builds file paths using the correct separator for whatever operating system the code is running on. Each argument is a component of the path:
import os
icon_path = os.path.join("D:\\", "abc", "resource", "logo.ico")
self.setWindowIcon(QIcon(icon_path))
This produces D:\abc\resource\logo.ico on Windows — correctly assembled, with no guesswork about separators.
Here's a complete minimal example using os.path.join:
import sys
import os
from PySide6.QtWidgets import QApplication, QMainWindow
from PySide6.QtGui import QIcon
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Absolute Path Icon Example")
icon_path = os.path.join("D:\\", "abc", "resource", "logo.ico")
self.setWindowIcon(QIcon(icon_path))
app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec()
Replace the path components with the actual location of your icon file.
Using pathlib.Path
Python 3 also includes the pathlib module, which gives you an object-oriented way to work with file paths. Many people find it more readable than os.path.join:
from pathlib import Path
icon_path = Path("D:/") / "abc" / "resource" / "logo.ico"
self.setWindowIcon(QIcon(str(icon_path)))
The / operator joins path components together, and pathlib handles separators for you. Note that QIcon expects a string, so we wrap the result in str().
Here's a full working example with pathlib:
import sys
from pathlib import Path
from PySide6.QtWidgets import QApplication, QMainWindow
from PySide6.QtGui import QIcon
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Pathlib Icon Example")
icon_path = Path("D:/") / "abc" / "resource" / "logo.ico"
self.setWindowIcon(QIcon(str(icon_path)))
app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec()
Why absolute paths are usually a bad idea
Hardcoding an absolute path like D:\abc\resource\logo.ico means the icon file must exist at exactly that location on every computer that runs your application. If you share your app with someone else — or package it for distribution — the path almost certainly won't match, and the icon will silently fail to load.
A much more reliable approach is to build paths relative to the script's own location. That way, as long as your icon file ships alongside your code, it will always be found.
Building paths relative to your script
You can use Python's __file__ variable to get the location of the currently running script, and then build paths from there. If your project looks like this:
my_app/
├── main.py
└── resources/
└── logo.ico
You can reference logo.ico like this:
import os
basedir = os.path.dirname(__file__)
icon_path = os.path.join(basedir, "resources", "logo.ico")
self.setWindowIcon(QIcon(icon_path))
Or with pathlib:
from pathlib import Path
basedir = Path(__file__).resolve().parent
icon_path = basedir / "resources" / "logo.ico"
self.setWindowIcon(QIcon(str(icon_path)))
This works no matter where the project folder is located on disk. It also keeps working after packaging with tools like PyInstaller.
Complete working example
Here's a full example using relative paths — the recommended approach for any application you plan to share or distribute:
import sys
import os
from PySide6.QtWidgets import QApplication, QMainWindow
from PySide6.QtGui import QIcon
# Get the directory where this script lives
basedir = os.path.dirname(__file__)
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Icon Example")
self.setGeometry(100, 100, 400, 300)
# Build the icon path relative to the script location
icon_path = os.path.join(basedir, "resources", "logo.ico")
self.setWindowIcon(QIcon(icon_path))
app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec()
To use this, create a resources folder next to your script and place your logo.ico file inside it.
If you're packaging your application for distribution and running into issues with icons not being found, take a look at our Packaging PySide6 applications for Windows with PyInstaller tutorial, which covers several strategies for bundling resource files with your app.
Create GUI Applications with Python & Qt6 by Martin Fitzpatrick
(PyQt6 Edition) The hands-on guide to making apps with Python — Over 15,000 copies sold!