Darkdetect
Darkdetect is a Python library designed to detect if the operating system is currently in Dark Mode. It supports macOS (10.14+), Windows (10 1607+), and Linux (with a dark GTK theme). This package is particularly useful for Python GUI applications (Tkinter, wx, PyQt, PySide, etc.) that need to adapt their interface based on the system's theme settings. The current version is 0.8.0, and its release cadence has been infrequent, with the last major update in December 2022.
Warnings
- gotcha The `darkdetect.theme()`, `isDark()`, and `isLight()` functions will return `None` if the operating system is not supported (e.g., older macOS/Windows versions, or Linux without a detectable GTK dark theme) or if the theme cannot be determined for other reasons.
- breaking Python 2.7 and Python versions older than 3.6 are no longer supported from `darkdetect` version 0.8.0 onwards.
- gotcha On macOS, the detection of the dark menu bar and dock option (available from macOS 10.10) is specifically not supported by `darkdetect`.
- gotcha When using the listener API on macOS in a bundled application where `sys.executable` is not a Python interpreter, the listener might not function correctly. Additionally, the macOS listener may leave unkilled processes when the application terminates.
- gotcha On Windows, calling `Listener.stop(None)` (to stop with no timeout) might not immediately terminate the underlying listener process until another theme change is detected. While no further callbacks will be made, the process might persist.
Install
-
pip install darkdetect -
pip install darkdetect[macos-listener]
Imports
- darkdetect
import darkdetect
Quickstart
import darkdetect
import threading
import time
# Check the current theme state
current_theme = darkdetect.theme()
print(f"Current OS theme: {current_theme}")
print(f"Is Dark mode: {darkdetect.isDark()}")
print(f"Is Light mode: {darkdetect.isLight()}")
# Example of using the listener for theme changes
def theme_changed_callback(new_theme: str):
print(f"[Listener] Theme changed to: {new_theme} at {time.time()}")
print("\nStarting a background listener (runs for 5 seconds)...")
# The darkdetect.Listener class offers more control over stopping.
# For a simple runnable quickstart, darkdetect.listener (a wrapper) is shown in docs,
# but for proper cleanup, using the Listener class explicitly is often better.
# We'll use the Listener class to demonstrate a controllable listener.
listener_instance = darkdetect.Listener(theme_changed_callback)
listener_thread = threading.Thread(target=listener_instance.listen, daemon=True)
listener_thread.start()
# Let the listener run for a few seconds to detect any immediate changes
time.sleep(5)
# Stop the listener gracefully
listener_instance.stop(timeout=1)
print("Background listener stopped.")