PySide6에서의 QSettings 가이드:
QSettings는 Qt 프레임워크에서 애플리케이션 설정을 저장하고 불러오는 데 사용되는 클래스임.
1. 생성 및 파일 위치 및 형식
1-1. QSettings 생성자:
다음과 같은 3가지 방식이 존재함.
QSettings(organization: str, application: str)
QSettings(filename: str, format: QSettings.Format)
QSettings(
format: QSettings.Format,
scope: QSettings.Scope,
organization: str,
application: str = ''
)
사용례는 다음과 같음 (3번째 방법은 Format과 Scope를 지정하는 방식으로 "참고: Format과 Scope 지정 방식"을 참고)
from PySide6.QtCore import QSettings
# 기본 방식
settings = QSettings("회사명", "애플리케이션명")
# 또는 특정 파일 사용
settings = QSettings("설정파일.ini", QSettings.IniFormat)
1-2. 설정 파일 저장 위치
QSettings는 기본방식으로 사용할 경우, 운영체제에 따라 설정 파일이 다른 위치에 저장됨:
- Windows:
- 레지스트리:
HKEY_CURRENT_USER\Software\회사명\애플리케이션명 - INI 파일 사용 시:
C:\Users\사용자명\AppData\Roaming\회사명\애플리케이션명.ini
- 레지스트리:
- macOS:
~/Library/Preferences/com.회사명.애플리케이션명.plist
- Linux/Unix:
~/.config/회사명/애플리케이션명.conf
1-3. 파일 이름을 직접 지정한 경우의 저장 위치
파일 이름을 직접 지정하면
- 상대 경로일 경우 현재 작업 디렉토리(Current Working Directory)를 기준으로 저장됨.
- 절대 경로를 사용하면 지정된 위치에 정확히 저장됩니다.
1-3-1. 파일 이름 지정 방식:
QSettings(filename: str, format: QSettings.Format)
- 주로 INI 파일로 저장됨: text로 저장하는 방식.
1-3-2. 사용예
이 방식의 간단한 사용례는 아래와 같음.
# 상대 경로 사용 (현재 작업 디렉토리 기준)
relative_settings = QSettings("settings.ini", QSettings.IniFormat)
print(f"상대 경로 설정 파일: {relative_settings.fileName()}")
# 출력 예: 상대 경로 설정 파일: /현재/작업/디렉토리/settings.ini
# 절대 경로 사용
import os
absolute_path = os.path.join(os.path.expanduser("~"), "Documents", "myapp_settings.ini")
absolute_settings = QSettings(absolute_path, QSettings.IniFormat)
print(f"절대 경로 설정 파일: {absolute_settings.fileName()}")
# 출력 예: 절대 경로 설정 파일: /Users/사용자명/Documents/myapp_settings.ini
참고: 현재 작업 디렉토리 확인하기
현재 작업 디렉토리가 어디인지 확인하고 싶다면:
import os
print(f"현재 작업 디렉토리: {os.getcwd()}")
# 만약 PyQt 애플리케이션에서 실행 파일의 디렉토리를 기준으로 설정 파일을 저장하고 싶다면:
import sys
app_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
app_settings_path = os.path.join(app_dir, "app_settings.ini")
app_settings = QSettings(app_settings_path, QSettings.IniFormat)
print(f"애플리케이션 디렉토리 기준 설정 파일: {app_settings.fileName()}")
__file__dunder는 현재 실행 중인 스크립트 파일의 경로를 가리키므로 이를 대신 사용가능함.- 단, 패키징된 애플리케이션에서는
__file__은 동작하지 않을 수 있으므로sys.argv[0]를 사용할 것. - 패키징된 경우,
sys.argv[0]는 exe파일에 해당됨.
1-4. Format과 Scope 지정 방식
1-4-1. QSettings.Format 열거형 값:
QSettings.NativeFormat # 운영체제 기본 형식 (Windows: 레지스트리, macOS: plist 등)
QSettings.IniFormat # INI 파일 형식
QSettings.InvalidFormat # 유효하지 않은 형식
1-4-2. QSettings.Scope 열거형 값:
QSettings.UserScope # 현재 사용자만을 위한 설정
QSettings.SystemScope # 모든 사용자를 위한 설정
1-4-3. 사용예
사용 방법은 다음 코드를 확인할 것.
from PySide6.QtCore import QSettings
# Format과 Scope 지정 방식
settings = QSettings(QSettings.IniFormat, QSettings.UserScope, "회사명", "애플리케이션명")
# 이 설정은 다음과 같은 위치에 INI 파일로 저장됩니다:
# Windows: C:\Users\사용자명\AppData\Roaming\회사명\애플리케이션명.ini
# macOS: ~/Library/Preferences/회사명/애플리케이션명.ini
# Linux: ~/.config/회사명/애플리케이션명.ini
print(f"설정 파일 경로: {settings.fileName()}")
# SystemScope 사용 예제 (관리자 권한이 필요할 수 있음)
system_settings = QSettings(QSettings.IniFormat, QSettings.SystemScope, "회사명", "애플리케이션명")
# 이 설정은 다음과 같은 위치에 저장됩니다:
# Windows: C:\ProgramData\회사명\애플리케이션명.ini
# macOS: /Library/Preferences/회사명/애플리케이션명.ini
# Linux: /etc/xdg/회사명/애플리케이션명.ini
print(f"시스템 설정 파일 경로: {system_settings.fileName()}")
1-5. 저장형식
1-5-1. INI 형식 (QSettings.IniFormat):
- 텍스트 기반 형식으로 저장.
- 키-값 쌍이 일반 텍스트로 저장되어 사람이 읽고 편집할 수 있음.
1-5-2. 네이티브 형식 (QSettings.NativeFormat):
- Windows: 레지스트리에 바이너리 형태로 저장.
- macOS: XML 기반 Property List (
.plist) 형식으로 저장 (실제로는 바이너리 형식이라pluitl등을 사용해야 텍스트로 확인 가능). - Linux/Unix: INI와 유사한 텍스트 기반
.conf파일로 저장.
다시 한번 강조하지만 파일 경로를 직접 지정할 경우 기본적으로 INI 형식(텍스트 기반)으로 저장됨.
❯❯ plutil -p ~/Library/Preferences/com.imagebrowser.Settings.plist
{
"lastDirectory" => "/Users/dsaint31/Desktop"
"recentDirectories" => [
0 => "/Users/dsaint31/Desktop"
1 => "/Users/dsaint31/Pictures"
]
}
2. 기본 사용법
2-1. 현재 설정 파일 경로 확인
2-1-1. fileName 메서드:
fileName() -> str
QSettings객체의 메서드임.
file_path = settings.fileName()
print(f"설정 파일 경로: {file_path}")
2-2. 설정 저장하기
2-2-1. setValue 메서드:
설정값을 키와 값의 쌍으로 저장.
setValue(key: str, value: Any) -> None
2-2-2. sync 메서드:
현재 변경사항을 storage에 저장.
sync() -> None
2-2-3. Example Code
# 다양한 타입의 값 저장
settings.setValue("category/text", "Hello World")
settings.setValue("category/number", 42)
settings.setValue("category/boolean", True)
settings.setValue("category/list", [1, 2, 3, 4])
settings.setValue("category/dict", {"key": "value"})
# 변경사항 storage에 저장
settings.sync()
2-3. 설정 불러오기
2-3-1. value 메서드:
설정값을 키를 통해 가져옴. 없을 경우 defaultValue에 설정된 값이 반환됨.
value(key: str, defaultValue: Any = None) -> Any
2-3-2. Example Code
# 기본값을 지정하면서 설정 불러오기
text = settings.value("category/text", "기본값")
number = settings.value("category/number", 0)
boolean = settings.value("category/boolean", False)
# 타입 지정 (PySide6에서는 타입 변환이 필요할 수 있음)
number = int(settings.value("category/number", 0))
boolean = bool(settings.value("category/boolean", False))
2-4. 그룹으로 관리하기:
2-4-1. beginGroup 메서드:
beginGroup 메서드는
- 설정 키에 공통 접두사를 지정하여 관련 설정들을 논리적으로 그룹화하고,
- 설정 키의 계층 구조를 쉽게 관리할 수 있게 해줌.
/로 직접 지정도 가능하지만, 여러개를 한꺼번에 다룰 때는 beginGroup이 보다 편함.
beginGroup(prefix: str) -> None
2-4-2. endGroup 메서드:
beginGroup메서드로 시작된 그룹의 prefix를 끝낼 때 사용함.
endGroup() -> None
2-4-3. Example Code:
# 그룹 시작
settings.beginGroup("UserPreferences")
# 그룹 내 값 설정
settings.setValue("theme", "dark")
settings.setValue("fontSize", 12)
settings.setValue("showToolbar", True)
# 그룹 종료
settings.endGroup()
# 그룹 내 값 읽기
settings.beginGroup("UserPreferences")
theme = settings.value("theme", "light")
fontSize = int(settings.value("fontSize", 10))
settings.endGroup()
# 슬래시(/)를 사용하여 직접 그룹 구조로 설정
settings.setValue("UserPreferences/theme", "dark")
# 그룹 외부에서 동일한 값에 접근하려면 전체 경로 필요
theme = settings.value("UserPreferences/theme", "light")
2-4. 배열 저장하기:
QSettings의 배열 저장 기능은 인덱스가 있는 동일한 타입의 여러 설정 값을 구조화된 방식으로 관리할 수 있음.
beginWriteArray()메서드로 배열 작성을 시작setArrayIndex()로 인덱스를 지정한 후setValue()를 호출하면, 내부적으로는 각 인덱스에 해당하는 고유 키가 생성되어 값이 저장됨.endArray()메서드로 배열 작성 종료.
2-4-1. beginWriteArray 메서드:
beginWriteArray(prefix: str, size: int = -1) -> None
2-4-2. setArrayIndex 메서드:
setArrayIndex(i: int) -> None
2-4-3. endArray 메서드:
endArray() -> None
2-4-4. Example Code
items = ["항목1", "항목2", "항목3"]
settings.beginWriteArray("recentItems")
for i, item in enumerate(items):
settings.setArrayIndex(i)
settings.setValue("name", item)
settings.endArray()
2-5. 배열 불러오기
작성과 사용이 유사하나, beginWriteArray() 대신 beginReadArray 메서드로 배열 읽기를 시작.
읽을 때는 value메서드를 사용함.
2-5-1. beginReadArray 메서드:
beginReadArray(prefix: str) -> int
2-5-2. Example Code
size = settings.beginReadArray("recentItems")
items = []
for i in range(size):
settings.setArrayIndex(i)
item = settings.value("name")
items.append(item)
settings.endArray()
print(f"최근 항목: {items}")
2-6. 배열 직접 사용하기.
다음과 같이 직접 /와 index를 통해 배열을 사용하는 방법도 가능.
# 배열 크기 저장
items = ["항목1", "항목2", "항목3"]
settings.setValue("recentItems/size", len(items))
# 각 배열 요소 저장
for i, item in enumerate(items):
settings.setValue(f"recentItems/{i}/name", item)
# 배열 불러오기
size = int(settings.value("recentItems/size", 0))
loaded_items = []
for i in range(size):
item = settings.value(f"recentItems/{i}/name", "")
loaded_items.append(item)
2-7. 설정 제거하기
2-7-1. remove 메서드:
키를 통해 특정 설정을 제거.
remove(key: str) -> None
2-7-2. clear 메서드:
전부 삭제.
clear() -> None
2-7-3. Example Code
# 특정 키 제거
settings.remove("category/text")
# 모든 설정 제거
settings.clear()
2-8. 그 외 메서드와 기능
2-8-1. contains 메서드:
현재 그룹 내의 키와 함께 모든 하위 그룹의 키도 검색 대상에 포함하여 지정된 키의 존재 여부를 확인.
즉, 전체 경로를 포함하여 검색하므로 "그룹/하위그룹/키" 형태로 지정된 중첩된 키의 존재도 확인할 수 있음.
contains(key: str) -> bool
- 특정 키가 존재하는지 확인함.
# 특정 키가 존재하는지 확인
if settings.contains("ui/theme"):
print("테마 설정이 존재합니다!")
else:
print("테마 설정이 없습니다. 기본값을 사용합니다.")
그룹 관련된 메서드를 사용하면 해당 그룹의 여러 키에 대한 확인이 보다 편해짐:
# 그룹 설정
settings.beginGroup("UserPreferences")
# 직계 키 확인 - 그룹명 없이 바로 키 이름만 사용
if settings.contains("theme"):
print("테마 설정이 존재합니다")
# 하위 그룹의 키 확인 - 하위 그룹명을 포함한 경로 사용
if settings.contains("colors/background"):
print("배경색 설정이 존재합니다")
settings.endGroup()
# 그룹 외부에서는 전체 경로 필요
if settings.contains("UserPreferences/theme"):
print("테마 설정이 존재합니다")
2-8-2. allKeys 메서드:
현재 그룹을 포함한 모든 하위 그룹의 키들을 포함하여 계층 구조 내의 모든 키를 완전한 경로("그룹/하위그룹/키" 형식)와 함께 문자열 리스트로 반환
allKeys() -> List[str]
- 모든 키 목록을 확인.
# 모든 키 목록 가져오기
all_keys = settings.allKeys()
print("저장된 모든 설정 키:")
for key in all_keys:
print(f" - {key}")
2-8-3. childGroups 메서드:
현재 그룹 내에 있는 모든 직계 하위 그룹의 이름을 문자열 리스트로 반환
childGroups() -> List[str]
- 자식 그룹을 반환함.
# 모든 그룹 이름 가져오기
groups = settings.childGroups()
print("설정 그룹 목록:")
for group in groups:
print(f" - {group}")
2-8-4. childKeys 메서드:
현재 그룹 내에 존재하는 모든 키의 목록을 문자열 리스트로 반환
childKeys() -> List[str]
- 현재 그룹의 모든 키를 가져옴.
# 현재 그룹의 모든 키 가져오기
settings.beginGroup("UserPreferences")
keys = settings.childKeys()
print("UserPreferences 그룹의 키 목록:")
for key in keys:
print(f" - {key}")
settings.endGroup()
2-8-5. status 메서드:
QSettings.status() 메서드는 현재 QSettings 객체의 오류 상태를 QSettings.Status 열거형 값으로 반환
- 설정 파일 작업 중 발생할 수 있는 문제를 감지하는 데 사용됨.
status() -> QSettings.Status
- 상태 확인.
- 반환되는 상태 값은 다음과 같음:
QSettings.NoError(오류 없음),QSettings.AccessError(파일 접근 권한 문제),QSettings.FormatError(파일 형식 손상)
# 설정 상태 확인
status = settings.status()
if status == QSettings.NoError:
print("설정 파일에 문제가 없습니다.")
elif status == QSettings.AccessError:
print("설정 파일 접근 오류!")
elif status == QSettings.FormatError:
print("설정 파일 형식 오류!")
3. 예제 코드
3-1. 활용 예제: 다양한 설정 파일 사용하기:
다음 코드는 다양한 위치와 범위의 설정 파일을 관리하는 ConfigManager 클래스를 구현함.
이를 통해 애플리케이션에서 여러 설정을 4개의 다른 위치에 생성 및 관리함
- 사용자별 기본 설정,
- 애플리케이션 폴더 내 휴대용 설정,
- 모든 사용자를 위한 시스템 설정, 그리고
- 사용자 문서 폴더 내 설정
from PySide6.QtCore import QSettings, QStandardPaths
import os
class ConfigManager:
def __init__(self):
# 1. 기본 사용자 설정 (운영체제 기본 위치)
self.user_settings = QSettings("MyCompany", "MyApp")
# 2. 휴대용 설정 (애플리케이션 폴더 내 INI 파일)
app_dir = os.path.dirname(os.path.abspath(__file__))
portable_path = os.path.join(app_dir, "portable_settings.ini")
self.portable_settings = QSettings(portable_path, QSettings.IniFormat)
# 3. 시스템 전체 설정 (모든 사용자용)
self.system_settings = QSettings(QSettings.IniFormat, QSettings.SystemScope,
"MyCompany", "MyApp")
# 4. 사용자 문서 폴더 내 설정
docs_dir = QStandardPaths.writableLocation(QStandardPaths.DocumentsLocation)
docs_config = os.path.join(docs_dir, "MyApp", "config.ini")
os.makedirs(os.path.dirname(docs_config), exist_ok=True)
self.docs_settings = QSettings(docs_config, QSettings.IniFormat)
print(f"기본 사용자 설정 위치: {self.user_settings.fileName()}")
print(f"휴대용 설정 위치: {self.portable_settings.fileName()}")
print(f"시스템 설정 위치: {self.system_settings.fileName()}")
print(f"문서 폴더 설정 위치: {self.docs_settings.fileName()}")
# 사용 예
config_manager = ConfigManager()
3-2. 실제 예제: 간단한 애플리케이션 설정 관리:
다음 코드는 QSettings를 활용하여 사용자 설정을 저장하고 불러오는 기능을 갖춘 간단한 PySide6 애플리케이션 예제임.
- 사용자가 색상을 선택하여 배경색을 변경하고 저장할 수 있음.
- 창의 위치와 상태가 저장되어 애플리케이션을 다시 실행했을 때 이전 상태를 그대로 복원함.
- 또한 설정 파일이 저장되는 경로를 화면에 표시하여 사용자가 어디에 설정이 저장되는지 확인할 수 있음.
import sys
from PySide6.QtCore import QSettings
from PySide6.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget, QPushButton, QLabel, QColorDialog
class SettingsExample(QMainWindow):
def __init__(self):
# 부모 클래스 초기화
super().__init__()
# 윈도우 기본 설정
self.setWindowTitle("QSettings 예제") # 윈도우 제목 설정
self.resize(400, 300) # 윈도우 초기 크기 설정 (너비 400px, 높이 300px)
# QSettings 객체 생성 - 회사명과 애플리케이션명 기반으로 설정 저장 위치 결정
# 운영체제별로 다른 위치에 설정이 저장됨:
# - Windows: 레지스트리 HKEY_CURRENT_USER\Software\MyCompany\SettingsExample
# - macOS: ~/Library/Preferences/com.MyCompany.SettingsExample.plist
# - Linux: ~/.config/MyCompany/SettingsExample.conf
self.settings = QSettings("MyCompany", "SettingsExample")
# 중앙 위젯 설정 - QMainWindow는 중앙 위젯이 필요함
central_widget = QWidget()
# 수직 레이아웃 생성 및 중앙 위젯에 설정
layout = QVBoxLayout(central_widget)
# 색상 표시 레이블 생성
# load_color() 메서드를 호출하여 저장된 색상을 가져오거나 기본값 사용
self.color_label = QLabel("색상 설정")
# 스타일시트를 사용하여 배경색 설정 - 저장된 색상 또는 기본값(흰색)
self.color_label.setStyleSheet(f"background-color: {self.load_color()};")
# 색상 변경 버튼 생성
change_color_btn = QPushButton("색상 변경")
# 버튼 클릭 시 change_color 메서드가 호출되도록 시그널 연결
change_color_btn.clicked.connect(self.change_color)
# 창 위치 저장 버튼 생성
save_position_btn = QPushButton("창 위치 저장")
# 버튼 클릭 시 save_window_geometry 메서드가 호출되도록 시그널 연결
save_position_btn.clicked.connect(self.save_window_geometry)
# 설정 파일 경로를 표시하는 레이블 생성
# fileName() 메서드로 현재 설정 파일의 실제 경로를 가져옴
path_label = QLabel(f"설정 파일 경로: {self.settings.fileName()}")
# 위젯들을 레이아웃에 순서대로 추가
layout.addWidget(self.color_label)
layout.addWidget(change_color_btn)
layout.addWidget(save_position_btn)
layout.addWidget(path_label)
# 중앙 위젯 설정
self.setCentralWidget(central_widget)
# 애플리케이션 시작 시 저장된 창 위치 불러오기
# 이전에 저장된 위치가 있으면 해당 위치로 창을 이동
self.load_window_geometry()
def change_color(self):
"""
색상 선택 대화상자를 열고 선택된 색상으로 레이블 배경색을 변경한 후 설정에 저장
"""
# QColorDialog를 사용하여 색상 선택 대화상자 표시
color = QColorDialog.getColor()
# 사용자가 유효한 색상을 선택했는지 확인 (취소 버튼을 누르지 않았는지)
if color.isValid():
# 선택한 색상으로 레이블의 배경색 변경
self.color_label.setStyleSheet(f"background-color: {color.name()};")
# 선택한 색상을 설정에 저장 ("ui/backgroundColor" 키 사용)
# color.name()은 "#RRGGBB" 형식의 16진수 색상 코드 반환
self.settings.setValue("ui/backgroundColor", color.name())
def load_color(self):
"""
설정에서 저장된 배경색을 불러옴. 저장된 값이 없으면 흰색(#ffffff)을 기본값으로 사용
Returns:
str: 16진수 색상 코드 ("#RRGGBB" 형식)
"""
# "ui/backgroundColor" 키에 저장된 값을 불러오고, 없으면 흰색(#ffffff)을 기본값으로 사용
return self.settings.value("ui/backgroundColor", "#ffffff")
def save_window_geometry(self):
"""
현재 창의 위치, 크기, 상태를 설정에 저장
"""
# QWidget.geometry()는 창의 위치와 크기를 포함하는 QRect 객체 반환
self.settings.setValue("window/geometry", self.geometry())
# QWidget.windowState()는 창의 상태를 나타내는 Qt.WindowState 반환
# (일반, 최대화, 최소화, 전체화면 등)
self.settings.setValue("window/state", self.windowState())
def load_window_geometry(self):
"""
설정에서 저장된 창의 위치, 크기, 상태를 불러와 적용
저장된 설정이 없으면 기본값(생성자에서 설정한 값) 유지
"""
# 저장된 창 위치 및 크기 불러오기
geometry = self.settings.value("window/geometry")
# 저장된 값이 있으면 적용
if geometry:
self.setGeometry(geometry)
# 저장된 창 상태 불러오기 (최대화, 최소화 등)
state = self.settings.value("window/state")
# 저장된 값이 있으면 적용
if state:
self.setWindowState(state)
# 메인 애플리케이션 실행 코드
if __name__ == "__main__":
# QApplication 인스턴스 생성 - 모든 Qt 애플리케이션에 필요
app = QApplication(sys.argv)
# SettingsExample 창 인스턴스 생성
window = SettingsExample()
# 창 표시
window.show()
# 애플리케이션 이벤트 루프 시작
# app.exec()는 애플리케이션이 종료될 때 반환값을 제공
# sys.exit()은 이 반환값을 시스템에 전달하여 애플리케이션 종료 상태를 알림
sys.exit(app.exec())
4. 주의사항 및 팁
4-1. 타입 변환:
- PySide6에서는 값을 불러올 때 타입 변환이 자동으로 이루어지지 않을 수 있음.
- 특히
bool과 Numeric Types (int,float)은 명시적으로 변환을 권장.
# 명시적 타입 변환
number = int(settings.value("number", 0))
is_enabled = settings.value("enabled", False) in [True, "true", "1", 1]
4-3. 설정 동기화:
- 중요한 설정을 변경한 후에는
sync()메서드를 호출하여 즉시 디스크에 반영할 것.
4-4. 설정 백업과 복원:
QSettings 객체를 사용하여 애플리케이션 설정을 안전하게 백업하고 복원하는 과정을 보여주는 예제임.
- 자세한 예외 처리 및
- 파일 잠금 방지 메커니즘을 사용함.
사용된
shutil은 Python 표준 라이브러리에 포함되어 있는 모듈로서
파일 복사, 이동, 삭제 등의 고수준 파일 작업을 제공함.이 모듈은
셸(명령 프롬프트나 터미널)에서 수행할 수 있는
파일 및 디렉토리 작업을 Python 코드로 제공하는 유틸리티 모듈임.
def backup_settings(settings, backup_path):
"""
QSettings 객체가 관리하는 설정 파일을 백업합니다.
Args:
settings (QSettings): 백업할 설정 객체
backup_path (str): 백업 파일이 저장될 경로
Returns:
bool: 백업 성공 시 True, 실패 시 False
"""
import shutil
import os
try:
# 현재 설정 파일의 경로를 얻습니다.
source_path = settings.fileName()
# 설정 파일이 존재하는지 확인합니다.
if not os.path.exists(source_path):
print(f"오류: 설정 파일이 존재하지 않습니다. ({source_path})")
return False
# 백업 파일이 저장될 디렉토리가 존재하는지 확인하고, 없으면 생성합니다.
backup_dir = os.path.dirname(backup_path)
if backup_dir and not os.path.exists(backup_dir):
os.makedirs(backup_dir)
# 설정 파일을 백업 경로로 복사합니다.
# copy2는 메타데이터(수정 시간 등)까지 함께 복사합니다.
shutil.copy2(source_path, backup_path)
print(f"설정이 {backup_path}에 성공적으로 백업되었습니다.")
return True
except Exception as e:
# 예외가 발생하면 오류 메시지를 출력하고 False를 반환합니다.
print(f"백업 중 오류 발생: {str(e)}")
return False
def restore_settings(backup_path, organization=None, application=None, settings_file=None):
"""
백업된 설정 파일을 복원합니다.
이 함수는 기존 QSettings 객체를 사용하지 않고, 새로운 QSettings 객체를 생성하여 반환합니다.
파일 잠금 문제를 방지하기 위해 기존 객체는 사용하지 않습니다.
Args:
backup_path (str): 백업 파일의 경로
organization (str, optional): 조직 이름. settings_file이 None일 때 필요합니다.
application (str, optional): 애플리케이션 이름. settings_file이 None일 때 필요합니다.
settings_file (str, optional): 설정 파일 경로. 이 값이 제공되면 organization과
application은 무시됩니다.
Returns:
QSettings: 복원된 설정을 가진 새 QSettings 객체, 실패 시 None
"""
import shutil
import os
from PySide6.QtCore import QSettings, QSettings
try:
if not os.path.exists(backup_path):
print(f"오류: 백업 파일이 존재하지 않습니다. ({backup_path})")
return None
# 대상 설정 파일의 경로를 결정합니다.
if settings_file:
# 특정 파일 경로가 제공된 경우
target_settings = QSettings(settings_file, QSettings.IniFormat)
target_path = settings_file
elif organization and application:
# 조직 및 애플리케이션 이름이 제공된 경우
temp_settings = QSettings(organization, application)
target_path = temp_settings.fileName()
# 임시 객체는 더 이상 필요하지 않으므로 해제합니다.
del temp_settings
else:
print("오류: 설정 파일 경로 또는 조직/애플리케이션 이름이 필요합니다.")
return None
# 대상 디렉토리가 존재하는지 확인하고, 없으면 생성합니다.
target_dir = os.path.dirname(target_path)
if target_dir and not os.path.exists(target_dir):
os.makedirs(target_dir)
# 백업 파일을 원래 위치로 복사합니다.
shutil.copy2(backup_path, target_path)
print(f"설정이 {backup_path}에서 {target_path}로 성공적으로 복원되었습니다.")
# 복원된 설정으로 새 QSettings 객체를 생성하여 반환합니다.
if settings_file:
return QSettings(settings_file, QSettings.IniFormat)
else:
return QSettings(organization, application)
except Exception as e:
# 예외가 발생하면 오류 메시지를 출력하고 None을 반환합니다.
print(f"복원 중 오류 발생: {str(e)}")
return None
# 사용 예제
def example_usage():
"""설정 백업 및 복원 사용 예제"""
from PySide6.QtCore import QSettings
import os
# 1. 기본 사용법
settings = QSettings("MyCompany", "MyApp")
settings.setValue("example/value", "test data")
settings.sync() # 변경사항을 디스크에 즉시 기록
# 설정 파일 경로 확인
original_path = settings.fileName()
print(f"원본 설정 파일: {original_path}")
# 백업 경로 설정 (현재 작업 디렉토리 사용)
backup_path = os.path.join(os.getcwd(), "settings_backup.ini")
# 2. 설정 백업
success = backup_settings(settings, backup_path)
if success:
# 기존 값 변경
settings.setValue("example/value", "changed data")
settings.sync()
print(f"설정 값 변경됨: {settings.value('example/value')}")
# 3. 설정 복원 (기존 객체는 사용하지 않음)
# 참고: 복원할 때는 원본 QSettings 객체를 사용하지 않고 새로 생성
restored_settings = restore_settings(backup_path, "MyCompany", "MyApp")
if restored_settings:
# 복원된 값 확인
print(f"복원된 설정 값: {restored_settings.value('example/value')}")
# 4. 특정 파일 경로를 사용한 백업/복원
file_settings = QSettings("custom_settings.ini", QSettings.IniFormat)
file_settings.setValue("custom/option", "file-based setting")
file_settings.sync()
file_backup_path = os.path.join(os.getcwd(), "custom_backup.ini")
if backup_settings(file_settings, file_backup_path):
# 파일 경로를 직접 지정하여 복원
restored_file_settings = restore_settings(file_backup_path,
settings_file="custom_settings.ini")
if restored_file_settings:
print(f"복원된 파일 설정 값: {restored_file_settings.value('custom/option')}")
4-5. 설정 파일 위치 지정:
애플리케이션별 설정 디렉토리를 생성하여 사용하는 방법 중 권장되는 것은 QStandardPaths를 이용하는 것임.
QStandardPaths
- 운영체제별 표준 디렉토리 경로를 제공하는 클래스임.
- 이를 통해 애플리케이션은 플랫폼에 독립적인 방식으로 시스템의 표준 위치에 접근할 수 있음.
유용한 QStandardPaths 위치 상수들:
AppDataLocation: 사용자의 애플리케이션 데이터를 저장하기 위한 표준 디렉토리 위치DesktopLocation: 사용자의 데스크톱 디렉토리DocumentsLocation: 사용자의 문서 디렉토리MusicLocation: 사용자의 음악 디렉토리MoviesLocation: 사용자의 동영상 디렉토리PicturesLocation: 사용자의 사진 디렉토리TempLocation: 임시 파일용 디렉토리HomeLocation: 사용자의 홈 디렉토리ConfigLocation: 애플리케이션별 설정 파일의 위치(QSettings의 기본 저장 위치)CacheLocation: 애플리케이션 캐시 데이터용 디렉토리GenericDataLocation: 공유 데이터를 저장하는 디렉토리RuntimeLocation: 런타임 데이터를 저장하는 디렉토리
from PySide6.QtCore import QStandardPaths, QSettings
import os
# 플랫폼 독립적인 방식으로 애플리케이션 설정 디렉토리 경로 찾기
# QStandardPaths.AppDataLocation은 각 OS에 맞는 설정 디렉토리를 반환:
# - Windows: C:\Users\사용자명\AppData\Local\MyApp
# - macOS: ~/Library/Application Support/MyApp
# - Linux: ~/.local/share/MyApp
app_data_dir = QStandardPaths.writableLocation(QStandardPaths.AppDataLocation)
# 애플리케이션 이름으로 하위 디렉토리 생성
# 여러 설정 파일을 체계적으로 관리하기 위한 전용 폴더
config_dir = os.path.join(app_data_dir, "MyApp")
# 디렉토리가 없으면 생성, 이미 존재하면 오류 발생하지 않음
# exist_ok=True 파라미터는 디렉토리가 이미 존재해도 예외를 발생시키지 않음
os.makedirs(config_dir, exist_ok=True)
# 설정 파일의 전체 경로 구성
# INI 형식의 설정 파일을 생성할 경로 지정
config_path = os.path.join(config_dir, "settings.ini")
# 지정된 경로에 INI 형식의 QSettings 객체 생성
# 이 방식은 설정 파일의 위치를 명시적으로 제어할 수 있어
# 포터블 애플리케이션이나 사용자 지정 위치에 설정을 저장할 때 유용
settings = QSettings(config_path, QSettings.IniFormat)
4-6. 다국어 지원:
다국어 설정을 관리하는 방법:
- 언어 코드(예: 'ko', 'en', 'ja')를 경로의 일부로 사용하여 각 언어별로 메시지를 구조적으로 분리해 저장.
- 저장된 메시지는 사용자가 선택한 언어(
user_language)에 따라 해당 언어 그룹에서 값을 불러오며, - 만약 해당 키에 대한 번역이 없을 경우 기본값을 반환하도록 구현.
# 언어별 설정 분리
settings.beginGroup(f"language/{current_language}")
settings.setValue("welcome_message", "환영합니다")
settings.endGroup()
# 언어 불러오기
settings.beginGroup(f"language/{user_language}")
welcome = settings.value("welcome_message", "Welcome")
settings.endGroup()
current_language 변수는 애플리케이션에서 현재 사용 중인 언어 코드를 나타내며, 일반적으로 다음과 같은 방법으로 설정
# 애플리케이션 시작 시 기본값 설정
current_language = "en" # 기본값으로 영어 설정
def initializeLanguage():
global current_language
# 저장된 설정에서 언어 불러오기
settings = QSettings("MyCompany", "MyApp")
saved_language = settings.value("preferences/language", "")
if saved_language:
current_language = saved_language
else:
# 시스템 언어 사용
system_lang = QLocale.system().name()[:2] # 'ko_KR' 등에서 'ko'만 추출
# 지원하는 언어 목록
supported_languages = ["en", "ko", "ja", "fr", "de"]
if system_lang in supported_languages:
current_language = system_lang
# 아니면 기본값 유지 (en)'Python' 카테고리의 다른 글
| [Py] SymPy (Symbolic Python) - Symbolic Computation (1) | 2025.06.05 |
|---|---|
| [Ex] scope 이해. (0) | 2025.05.12 |
| [Programming] SOLID 원칙 (0) | 2025.04.28 |
| [DL] default collate_fn - PyTorch (0) | 2025.04.26 |
| [Py] importlib.metadata: Package 정보 확인 (0) | 2025.04.23 |