pysimplegui之讀寫配置項操作
使用者設定 API
在 4.30.0 版中,有一組新的 API 呼叫可用於幫助“使用者設定”。將使用者設定視為自動寫入硬碟的字典。基本上就是這樣。
在 4.50.0 版中,除了現有的 JSON 檔案格式外,還添加了對 INI 檔案的支援。
雖然使用 JSON 或配置檔案來儲存和載入設定字典並不是很困難,但如果要將設定儲存為 GUI 的一部分,仍然需要編寫程式碼。由於基於 GUI 的程式具有“設定”並不少見,因此將這種功能構建到 PySimpleGUI 中是有意義的。顯然,您仍然可以使用自己的方法來儲存設定,但如果您正在尋找一種簡單易行的方法,那麼這些呼叫可能會非常簡單。
已經編寫了一些使用 JSON 檔案儲存設定的演示程式。
使用者設定儲存在 Python 字典中,該字典儲存到磁碟/從磁碟載入。因此,個人設定是字典的鍵。您不需要顯式讀取或寫入檔案。更改任何條目都會導致檔案被儲存。如果尚未讀取任何條目,則讀取任何條目將導致讀取該檔案。
兩個介面
有兩種方法可以訪問使用者設定
- 使用者設定函式呼叫
UserSettings
班級_
它們都提供相同的基本操作。類介面的另一個好處是能夠使用與 Python 字典相同的語法訪問各個設定。
如果要使用 INI 檔案,則需要使用物件介面。
函式介面呼叫列表
功能 | 描述 |
---|---|
使用者設定 | 以字典形式返回設定 |
user_settings_delete_entry | 刪除設定 |
使用者設定刪除檔名 | 刪除設定檔案 |
user_settings_file_exists | 如果指定的設定檔案存在,則返回 True |
使用者設定檔名 | 返回當前設定檔案的完整路徑和檔名 |
user_settings_get_entry | 返回設定的值。如果未找到設定,則返回指定的預設值 |
使用者設定載入 | 從設定檔案載入字典。這通常不需要 |
user_settings_save | 將設定儲存到當前或新指定的檔案。通常不需要 |
user_settings_set_entry | 將條目設定為特定值 |
user_settings_write_new_dictionary |
將指定的字典寫入設定檔案 |
運營
呼叫可分為 2 類。
- 檔案操作
- 設定操作
檔案操作涉及使用 JSON 檔案本身。它們包括: * 設定路徑和/或檔名 * 載入/儲存檔案(這些是可選的,因為儲存載入/儲存是自動完成的) * 刪除設定檔案 * 檢查設定檔案是否存在
一般而言,使用通常是字串的鍵來指定設定。設定操作用於處理單個設定,包括: * 獲取設定的值(如果未找到則返回預設值) * 設定設定的值(也將設定儲存到磁碟)
任何設定操作都可能導致檔案被寫入。這是因為如果未找到設定,“get”操作可以包括返回預設值。這意味著在您的設定字典中建立了一個新條目,該條目以前不存在。由於建立了一個新條目,這意味著它也需要寫入磁碟。
檔名
設定檔名預設使用添加了副檔名“.json”的 Python 檔案的檔名。如果您的 Python 程式被呼叫test.py
,那麼您的預設設定檔名將是test.json
.
除了具有預設值的檔名之外,檔案的路徑也具有預設值。預設值取決於您的作業系統。
作業系統 | 預設路徑 |
---|---|
視窗 | \user\user_name\AppData\Local\PySimpleGUI\settings |
Linux | ~/.config/PySimpleGUI/settings |
蘋果電腦 | ~/庫/應用程式支援/PySimpleGUI/settings |
呼叫使用者設定 API 時,如果引數名為filename
,您可以指定完整路徑或僅指定檔名。這將為您省去在程式碼中拆分路徑和檔名的麻煩。如果您僅指定路徑,則檔名將新增到該路徑並按照之前定義的方式命名。
與 PySimpleGUI 的其餘部分一樣,這個想法是讓您編寫儘可能少的程式碼。檔名和路徑的預設值應該適合您使用。它們將儲存在系統上用於儲存使用者設定的位置。
設定檔名
如果您想檢視當前設定的檔名是什麼,那麼您可以user_settings_filename()
不帶引數呼叫,您將獲得絕對路徑和檔名。
為了使指定資料夾和檔名的程式碼儘可能簡單,這兩個部分在指定設定檔名稱的呼叫中分開。但是,也可以提供完整且完整的資料夾 + 檔名。
設定檔案的預設檔名是呼叫使用者設定 API 的檔名,.py
副檔名更改為.json
副檔名。如果您的原始檔被呼叫demo.py
,那麼您的設定檔名將是demo.json
.
僅設定檔名
如果您想控制檔案的名稱和/或設定檔案的路徑,那麼您將使用user_settings_filename
呼叫。該函式有 2 個引數。
user_settings_filename(filename=None, path=None)
如果您僅設定路徑,則檔名將預設為已描述的值。如果您只設置檔名,那麼路徑將是預設路徑,具體取決於您的作業系統。有關每個作業系統的位置,請參見上表。
import PySimpleGUI as sg
sg.user_settings_filename(filename='my_settings.json')
print(sg.user_settings_filename())
如果您在 Windows 上執行,則執行此程式碼的結果將在控制檯上列印:
C:\Users\your_use_name\AppData\Local\PySimpleGUI\settings\my_settings.json
您不限於將設定檔案命名為 .json 的副檔名。這只是 PySimpleGUI 使用的預設擴充套件。你可以使用任何你想要的擴充套件,包括沒有擴充套件。
僅設定路徑
也許您不關心設定檔名本身,但您確實關心設定的儲存位置。假設您希望將設定儲存在與 Python 原始檔相同的資料夾中。指定path='.'
將實現這一點。
設定完全限定的檔名
如果要指定設定檔案的完整絕對路徑和檔名,可以使用 filename 引數來完成。不要只傳遞檔名,而是傳遞完全限定的路徑和檔名。如果您想命名您的設定檔案a:\temp\my_settings
,那麼您的呼叫將如下所示:
sg.user_settings_filename(filename=r'a:\temp\my_settings')
您不需要將檔案分解為 2 個引數。如果你願意,你可以。等效於使用 2 個引數的上述呼叫將是:
sg.user_settings_filename(filename='my_settings' , path=r'a:\temp')
獲取當前檔名
不帶引數呼叫user_settings_filename
將返回設定檔案的完整路徑和檔名作為單個字串。
檔案載入/儲存
一般來說,您不需要載入或儲存設定檔案。每次更改後都會自動儲存。
請注意,讀取設定也可能導致檔案被寫入。如果您讀取了一個設定並且該設定不存在,那麼您的呼叫user_settings_get_entry
將返回您指定的預設值。結果,字典用這個預設值更新,作為回報,檔案也用這個值寫入。
您可能想要顯式讀取/載入設定檔案的一種情況是,如果您希望它被另一個程式修改。
像 PySimpleGUI 一樣,儘可能多地自動為您完成。這包括儲存和載入設定檔案的要求。甚至命名您的設定檔案也是可選的。
類UserSettings
介面
該類UserSettings
使使用設定看起來像 Python 字典。熟悉的 [ ] 語法用於讀取、寫入和刪除條目。
建立UserSettings
物件
第一步是建立您的設定物件。引數與呼叫user_settings_filename
函式相同。如果要使用預設值,則保持引數不變。
settings = sg.UserSettings()
這與呼叫相同sg.user_settings_filename()
使用 [ ] 語法讀取、寫入和刪除單個設定
第一個操作是建立使用者設定物件。
settings = sg.UserSettings()
要讀取設定,使用字典式 [ ] 語法。如果專案的名稱是'-item-'
,那麼讀取值是通過寫入來實現的
item_value = settings['-item-']
編寫設定的語法相同,但表示式相反。
settings['-item-'] = new_value
要刪除一個專案,再次使用字典樣式語法。
del settings['-item-']
您也可以呼叫 delete_entry 方法來刪除條目。
settings.delete_entry('-item-')
UserSettings
方法
您會UserSettings
在呼叫參考文件中找到所有可用的方法的詳細資訊。
特別是使用 [ ] 表示法無法實現的一項操作是具有預設值的“get”操作。對於字典,這個方法是get
,對於UserSettings
類,這個方法也被呼叫get
。如果在字典中找不到鍵,它們都有一個可選的第二個引數,表示“預設值”。
如果您希望使用 key 的設定'-item-'
返回一個空字串''
,而不是None
如果找不到他們的 key,那麼您可以使用此程式碼來實現:
value = settings.get('-item-', '')
它與您習慣用於字典的語法相同。
預設值
通常預設值是None
如果沒有找到鍵並且您使用括號格式獲取條目的值:
item_value = settings['-item-']
您可以通過呼叫更改預設值settings.set_default_value(new_default)
。這將設定預設值以在未找到金鑰的情況下返回。請注意,當出現關鍵錯誤時不會引發異常(請參閱下一節有關錯誤處理的內容)。而是返回預設值並顯示警告。
顯示設定字典
類介面可以輕鬆轉儲字典。如果您列印 UserSettings 物件,您將獲得字典的列印輸出。
請注意,如果您尚未對設定執行任何操作,則需要從磁碟“載入”設定。
settings = sg.UserSettings()
settings.load()
print(settings)
如果您要在建立物件後列印字典,則load
不需要
settings = sg.UserSettings()
print(settings['-item-'])
print(settings)
使用函式呼叫介面列印字典:
print(sg.user_settings())
使用者設定的錯誤處理
從 GUI 的角度來看,使用者設定對 GUI 操作本身並不重要。沒有任何設定會導致您的視窗無法執行。因此,使用者設定中發生的錯誤是“軟錯誤”。如果可能,將顯示一條錯誤訊息以及有關您如何呼叫該函式的資訊,然後繼續執行。
將這些視為軟錯誤並因此不引發異常的一個原因是引發異常會使您的 GUI 崩潰。如果您已經重定向了您的輸出(許多 GUI 都會這樣做),那麼您將看不到任何錯誤資訊,並且您的視窗將簡單地消失。如果你雙擊一個 .py 檔案來啟動你的 GUI,如果 GUI 崩潰,GUI 和控制檯視窗都會立即消失,沒有任何資訊可以幫助你除錯問題。
唯一可能發生錯誤的時間是在檔案操作期間。通常發生這些錯誤是因為您指定了錯誤的路徑,或者您沒有指定路徑的寫入許可權。
示例錯誤訊息。如果您執行此程式碼:
def main():
sg.user_settings_filename(path='...')
sg.user_settings_set_entry('-test-',123)
然後在嘗試設定“-test-”條目時會出現錯誤,因為'...'
它不是有效路徑。
*** Error saving settings to file:***
...\scratch_1065.json [Errno 2] No such file or directory: '...\\scratch_1065.json'
The PySimpleGUI internal reporting function is save
The error originated from:
File "C:/Users/mike/.PyCharmCE2019.1/config/scratches/scratch_1065.py"
line 8
in main
sg.user_settings_set_entry('-test-',123)
您應該能夠輕鬆找出這些錯誤,因為它們是檔案操作,並且錯誤訊息清楚地詳細說明了發生的事情以及呼叫的來源。
消除錯誤
如果您不希望在控制檯上看到任何錯誤訊息,那麼您可以將錯誤輸出靜音。
使用類介面時,有一個引數silent_on_error
可以設定為True
。
對於函式介面,呼叫函式user_settings_silent_on_error()
並將引數設定為True
配置 INI 檔案支援
與 JSON 相比,使用 INI 檔案有一些優勢,尤其是當人們要直接修改設定檔案時。
要指定使用 INI 檔案而不是 JSON,請use_config_file=True
在建立UserSetting
物件時設定引數。
settings = sg.UserSettings('my_config.ini', use_config_file=True, convert_bools_and_none=True)
請注意特定於 .ini 檔案的 2 個引數: *use_config_file
- 設定True
為表示您正在使用 INI 檔案 *convert_bools_and_none
- 預設為True
.通常 INI 檔案中的所有設定都是字串。此引數將 'True'、'False' 和 'None' 轉換為 Python 值True
,False
,None
還添加了一種附加方法delete_section
,該方法將從 INI 檔案中刪除整個部分。
示例檔案
讓我們使用它作為我們的示例 INI 檔案:
[My Section]
filename = test1234
filename2 = number 2
filename3 = number 3
[Section 2]
var = 123
[Empty]
[last section]
bool = True
獲取/設定條目
就像 JSON 檔案一樣,您可以使用 UserSettings 類通過使用[ ]
符號或呼叫get
和set
方法來訪問各個設定。
INI 檔案支援的最大區別是添加了一個額外的查詢/引數,即部分名稱。
要訪問var
section中的條目Section 2
,您可以使用這些中的枯萎:
settings['Section 2']['var']
settings['Section 2'].get('var', 'Default Value')
使用該get
方法的優點是,如果條目不存在,則將返回預設值。
要設定條目,您還有 2 個選擇:
settings['Section 2']['var'] = 'New Value'
settings['Section 2'].set('var', 'New Value')
訪問 INI 檔案部分
建立UserSettings
物件後,您將使用 2 個鍵而不是 JSON 使用的 1 個鍵來訪問條目。
要訪問整個部分,您將編寫:
settings['section']
要獲得所有“我的部分”,它將是:
settings['My Section']
它返回一個行為很像字典的部分物件。
要訪問某個部分中的值,請再新增一個查詢。要獲取該部分中filename
設定的值,請My Section
使用以下程式碼完成:
settings['My Section']['filename']
刪除條目
要刪除單個條目,您可以使用幾種不同的技術。一是使用del
del settings['My Section1']['test']
這將刪除該test
部分中的設定My Section1
您也可以通過呼叫delete_entry
方法來做到這一點
settings.delete_entry(section='My Section1', key='test')
刪除部分
如果要刪除整個部分,有兩種方法可以做到這一點。一種是呼叫方法UserSettings.delete_section
並傳入要刪除的部分的名稱。
settings.delete_section(section='My Section1')
另一種是查詢該部分,然後呼叫delete_section
該部分。
settings['My Section1'].delete_section()
INI 檔案的列印設定
如果您為 INI 檔案列印(或轉換為字串)節或 UserSettings 物件,那麼您將獲得格式良好的輸出,其中顯示節以及每個節中的設定。
回到前面的示例 INI 檔案。列印此檔案的 UserSettings 物件會產生以下輸出:
My Section:
filename : test1234
filename2 : number 2
filename3 : number 3
Section 2:
var : 123
Empty:
last section:
bool : True
INI 檔案註釋(警告)
如果您使用測試編輯器建立了一個 INI 檔案,或者它是由 Python 建立的輸出,那麼在編寫檔案時,您的註釋將被刪除。正在將程式碼新增到 PySimpleGUI 以合併您的評論,但程式碼尚未完成。你要麼暫時忍受這個限制,要麼編寫自己的合併程式碼。
是的,我知道,這很糟糕,但計劃是克服這個 Python 限制。
使用者設定鍵的編碼約定
使用者設定提示了一個新的編碼約定,該約定已新增到 PySimpleGUI 示例中。正如您可能知道的那樣,佈局中的鍵具有格式'-KEY-
'.對於 UserSettings,使用了類似的格式,但字串不是全部大寫,而是字元小寫。在下面的示例中,“檔名”的使用者設定有一個使用者設定鍵'-filename-'
。在您的專案中擁有編碼約定是一件好事。當然,您不必遵循這一點,但我們敦促您為程式碼中有意義的位置建立自己的位置。你可以說 PEP8 是整個 Python 語言的一個巨大的編碼約定。您不必遵循它,但大多數 Python 程式設計師都會這樣做。我們“按照慣例”遵循它。
在 PySimpleGUI 中執行此操作的原因是可以立即識別鍵。也許您的應用程式有您使用的字典。如果您遵循元素鍵的格式'-KEY-'
和使用者設定鍵的格式的 PySimpleGUI 編碼約定'-key-'
,那麼您將立即瞭解特定鍵的用途。您的公司可能有自己的編碼約定,因此如果合適,請遵循這些約定,而不是您在 PySimpleGUI 示例中看到的。
示例使用者設定用法
可能使用的主要位置設定之一是檔名/資料夾名稱。您運行了多少次相同的程式並需要輸入相同的檔名?即使檔名在您的剪貼簿上,每次執行程式碼時將其貼上到輸入欄位中仍然很麻煩。如果您的程式記住您輸入的最後一個值,會不會簡單得多?嗯,這正是開發這套 API 的原因......再次,這種能力獲得了生命的懶惰。
如果您希望Input
元素預設為設定中的條目,則只需將第一個引數 (default_text
) 設定為設定檔案中的設定值。
假設您的佈局有這個典型的檔案輸入行:
[sg.Input(key='-IN-'), sg.FileBrowse()]
要自動填寫Input
最後輸入的值,請使用以下佈局行:
[sg.Input(sg.user_settings_get_entry('-filename-', ''), key='-IN-'), sg.FileBrowse()]
當您的使用者單擊確定或以積極的方式(而不是取消)關閉視窗時,然後新增此語句以儲存該值。
sg.user_settings_set_entry('-filename-', values['-IN-'])
這是一個完整的程式,演示了這種使用使用者設定的方式
import PySimpleGUI as sg
layout = [[sg.Text('Enter a filename:')],
[sg.Input(sg.user_settings_get_entry('-filename-', ''), key='-IN-'), sg.FileBrowse()],
[sg.B('Save'), sg.B('Exit Without Saving', key='Exit')]]
window = sg.Window('Filename Example', layout)
while True:
event, values = window.read()
if event in (sg.WINDOW_CLOSED, 'Exit'):
break
elif event == 'Save':
sg.user_settings_set_entry('-filename-', values['-IN-'])
window.close()
在 2 行程式碼中,您讓使用者的生活變得如此輕鬆。而且,通過不為您的檔案指定位置和名稱,這些設定會被儲存在視線之外/腦海中。如果您希望將設定與您的程式檔案一起儲存以便更明顯,請在佈局之前新增以下語句:
sg.user_settings_filename(path='.')
使用帶有 [ ] 語法的 UserSettings 類的示例
可以使用UserSettings
類和 [ ] 查詢語法編寫相同的示例。
這是與上面相同的程式。
import PySimpleGUI as sg
settings = sg.UserSettings()
layout = [[sg.Text('Enter a filename:')],
[sg.Input(settings.get('-filename-', ''), key='-IN-'), sg.FileBrowse()],
[sg.B('Save'), sg.B('Exit Without Saving', key='Exit')]]
window = sg.Window('Filename Example', layout)
while True:
event, values = window.read()
if event in (sg.WINDOW_CLOSED, 'Exit'):
break
elif event == 'Save':
settings['-filename-'] = values['-IN-']
window.close()
如果您將這兩個示例放在同一個檔案中,以便一個接一個地執行,您會發現使用了相同的設定檔案,因此第一個示例中儲存的值將被第二個示例讀取。
增加了一行程式碼:
settings.set_default_value('') # Set the default not-found value to ''
嚴格來說,不需要這一行,因為 Input Element 現在None
與 的值相同''
,但為了產生相同的結果,我添加了這行程式碼。
演示程式
有許多演示程式展示瞭如何使用 UserSettings 為使用者建立更豐富的體驗,方法是記住最後一次輸入到輸入元素中的值,或者新增一個包含先前輸入值歷史的組合框。這些升級使 GUI 更易於使用,尤其是當您發現自己輸入相同的值或使用相同的檔案/資料夾時。
簡短的警告 - 使用者設定一直存在
如果您使用的是預設路徑,請記住,之前執行的檔案可能具有仍在設定檔案中的舊設定。如果您忘記了之前編寫的設定,您可能會感到困惑。看不到檔名可能會有這樣的缺點。
此外,由於每次更新後設置都會自動儲存,因此很容易意外覆蓋以前儲存的設定。如果您想避免這種情況,那麼最好在程式碼中使用字典,然後在準備好將其提交到磁碟時顯式儲存字典。
要將 Python 字典儲存到設定檔案中,只需呼叫user_settings_write_new_dictionary(dict)
,將字典作為引數傳遞。