用戶設置 API
在 4.30.0 版中,有一組新的 API 調用可用於幫助“用戶設置”。將用戶設置視為自動寫入硬盤的字典。基本上就是這樣。
在 4.50.0 版中,除了現有的 JSON 文件格式外,還添加了對 INI 文件的支持。
雖然使用 JSON 或配置文件來保存和加載設置字典並不是很困難,但如果要將設置保存為 GUI 的一部分,仍然需要編寫代碼。由於基於 GUI 的程序具有“設置”並不少見,因此將這種功能構建到 PySimpleGUI 中是有意義的。顯然,您仍然可以使用自己的方法來保存設置,但如果您正在尋找一種簡單易行的方法,那么這些調用可能會非常簡單。
已經編寫了一些使用 JSON 文件存儲設置的演示程序。您可以預期此功能將在未來的更多演示中出現,因為它現在是 PySimpleGUI 的一部分。
用戶設置存儲在 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)
,將字典作為參數傳遞。
文檔來來源https://pysimplegui.readthedocs.io/en/latest/