Python如何讀取配置文件?configparser詳解

configparser能讀取ini風格文件,結構由節、選項組成,支持注釋,適用于簡單配置。1. 文件格式為[section]下多個key=value或key: value,支持#或;注釋;2. 局限性包括不支持嵌套結構、復雜數據類型,僅適合扁平化配置;3. 常見問題如鍵名默認不區分大小寫、值均為字符串需手動轉換、路徑處理需注意絕對路徑;4. 可動態修改并保存配置,通過賦值操作修改選項,調用config.write()寫回文件。

Python如何讀取配置文件?configparser詳解

python要讀取配置文件,尤其是不太復雜的、結構清晰的INI風格文件時,configparser庫通常是我的首選。它內置在Python標準庫里,用起來非常順手,能幫助我們把程序配置和代碼邏輯清晰地分離。

Python如何讀取配置文件?configparser詳解

解決方案

假設我們有一個名為 config.ini 的配置文件,內容可能長這樣:

Python如何讀取配置文件?configparser詳解

[database] host = localhost port = 5432 user = admin password = secure_password ; 這是一個注釋  [server] bind_ip = 0.0.0.0 port = 8080 debug_mode = True max_connections = 100

要讀取它,Python代碼可以這樣寫:

立即學習Python免費學習筆記(深入)”;

import configparser import os  # 獲取當前腳本所在目錄,構建config.ini的絕對路徑 # 這樣即使腳本在不同位置被調用,也能找到配置文件 current_dir = os.path.dirname(os.path.abspath(__file__)) config_file_path = os.path.join(current_dir, 'config.ini')  config = configparser.ConfigParser()  try:     # 嘗試讀取配置文件     config.read(config_file_path, encoding='utf-8')      # 訪問配置項     print("--- 數據庫配置 ---")     db_host = config['database']['host']     db_port = config.getint('database', 'port') # 獲取整數     db_user = config.get('database', 'user', fallback='guest') # 帶默認值     print(f"主機: {db_host}")     print(f"端口: {db_port}")     print(f"用戶: {db_user}")      print("n--- 服務器配置 ---")     server_ip = config['server']['bind_ip']     server_port = config.getint('server', 'port')     debug_mode = config.getboolean('server', 'debug_mode') # 獲取布爾值     max_connections = config.getint('server', 'max_connections')     print(f"綁定IP: {server_ip}")     print(f"端口: {server_port}")     print(f"調試模式: {debug_mode}")     print(f"最大連接數: {max_connections}")      # 嘗試訪問不存在的配置項,并提供默認值     non_existent_value = config.get('server', 'timeout', fallback='60s')     print(f"超時設置 (不存在則取默認): {non_existent_value}")  except configparser.NoSectionError as e:     print(f"錯誤: 配置文件中缺少某個節: {e}") except configparser.NoOptionError as e:     print(f"錯誤: 配置文件中某個節缺少選項: {e}") except FileNotFoundError:     print(f"錯誤: 配置文件 '{config_file_path}' 未找到。請確保它存在于腳本同目錄下。") except Exception as e:     print(f"讀取配置文件時發生未知錯誤: {e}") 

configparser究竟能讀懂什么格式的文件?它的局限性在哪?

configparser 的設計初衷就是為了處理INI風格的配置文件,這種格式其實非常簡單:它由若干個“節”(section)組成,每個節下面包含多個“選項”(option),每個選項都是一個鍵值對。節名用方括號 [] 包裹,選項通常是 key = value 或 key: value 的形式。它支持以 # 或 ; 開頭的行作為注釋。我個人覺得,這種結構對于存儲簡單的應用程序配置、數據庫連接信息、或者一些開關量參數來說,簡直是完美契ate。

Python如何讀取配置文件?configparser詳解

它的局限性也挺明顯的。configparser 不支持復雜的嵌套結構,比如像json或YAML那樣多層級的對象或列表。如果你需要存儲一個配置列表,比如多個數據庫連接信息,或者一個復雜的網絡拓撲結構,configparser 就顯得力不從心了。它會把所有值都當作字符串來處理,雖然提供了 getint()、getboolean()、getfloat() 這樣的輔助方法進行類型轉換,但那也只是針對少數基本類型。一旦你需要更復雜的數據結構,例如一個字典列表或者一個深層嵌套的配置,你可能就需要轉向 json 庫或者 pyyaml 庫了。所以,我的經驗是,對于簡單的、扁平化的配置,configparser 足夠了,但如果需求復雜起來,就得考慮更強大的序列化工具了。

用configparser,我踩過哪些坑?又學到了哪些好習慣?

說實話,剛開始用 configparser 的時候,我也踩過幾個小坑,但這些經歷也讓我學到了不少好習慣。

一個常見的“坑”就是默認的鍵名不區分大小寫。比如你配置文件里寫的是 DebugMode = True,但代碼里你用 config[‘server’][‘debugmode’] 也能取到值。這在某些情況下可能導致不易察覺的bug,因為你可能以為大小寫敏感,結果發現不是。不過,configparser 在Python 3.2+ 版本中默認是大小寫不敏感的,如果你需要嚴格的大小寫匹配,可以在創建 ConfigParser 實例時傳入 optionxform=str。我通常會養成習慣,配置文件里的鍵名都用小寫加下劃線,保持一致性。

另一個問題是值都是字符串。你從配置文件里讀出來的所有值,哪怕看起來是數字或布爾值,configparser 都會先把它當作字符串。如果你直接拿來做數學運算或者邏輯判斷,就會出問題。比如 config[‘server’][‘port’] 取出來是 ‘8080’,而不是 8080。所以,養成使用 getint()、getfloat()、getboolean() 這些方法的好習慣非常重要。它們會幫你自動完成類型轉換,如果轉換失敗還會拋出 ValueError,這樣你就能及時發現配置錯誤。

再來就是缺少節或選項時的錯誤處理。如果你嘗試訪問一個不存在的節或選項,configparser 會拋出 NoSectionError 或 NoOptionError。這在程序運行時是致命的。為了讓程序更健壯,我通常會用 config.get(‘section’, ‘option’, fallback=’default_value’) 來獲取配置,這樣即使配置項不存在,程序也能拿到一個默認值繼續運行。或者,你也可以用 try…except 塊來捕獲這些特定的錯誤,給用戶更友好的提示。我個人更傾向于使用 get() 的 fallback 參數,它讓代碼看起來更簡潔。

最后一點,路徑問題。有時候我把配置文件放在項目根目錄,但腳本在子目錄里運行,結果就報 FileNotFoundError。解決這個問題的方法是,在讀取配置文件之前,先用 os.path.dirname(os.path.abspath(__file__)) 獲取當前腳本的絕對路徑,然后用 os.path.join() 來拼接配置文件的完整路徑。這樣無論腳本在哪里被執行,它都能找到它“身邊”的配置文件。這是一個小細節,但能省去不少調試時間。

配置文件讀寫之外,configparser還能幫我做些什么?比如修改和保存?

configparser 不僅僅能讀取配置文件,它還能讓你在程序運行時動態地修改配置,并將這些修改保存回文件中。這對于那些需要用戶自定義設置、或者程序運行狀態需要持久化的場景來說,非常實用。

要修改或添加配置,操作起來也很直觀。你可以像操作字典一樣去添加新的節,或者修改現有節下的選項值。比如,如果我想在程序里修改數據庫的端口,或者添加一個新的日志配置節,我可以這樣做:

import configparser import os  config_file_path = 'config.ini' # 假設配置文件就在當前目錄  config = configparser.ConfigParser() config.read(config_file_path, encoding='utf-8')  # 修改現有配置 if 'database' in config:     config['database']['port'] = '5433' # 注意,這里賦值時仍然是字符串  # 添加新的節和選項 if 'logging' not in config:     config['logging'] = {} # 創建一個新節 config['logging']['level'] = 'INFO' config['logging']['file'] = '/var/log/my_app.log' config['logging']['max_size'] = '10MB'  # 刪除一個選項(如果需要) # if 'server' in config and 'max_connections' in config['server']: #     del config['server']['max_connections']  # 將修改后的配置寫回文件 try:     with open(config_file_path, 'w', encoding='utf-8') as configfile:         config.write(configfile)     print(f"配置文件 '{config_file_path}' 已成功更新。") except IOError as e:     print(f"寫入配置文件時發生錯誤: {e}")  # 再次讀取,驗證修改 print("n--- 更新后的配置 ---") updated_config = configparser.ConfigParser() updated_config.read(config_file_path, encoding='utf-8') print(f"數據庫新端口: {updated_config['database']['port']}") if 'logging' in updated_config:     print(f"日志級別: {updated_config['logging']['level']}")

需要注意的是,當你通過 config[‘section’][‘option’] = ‘value’ 這種方式賦值時,值總是以字符串形式存儲的。configparser 在寫入時會保持這種字符串形式。當調用 config.write(configfile) 時,它會把當前 ConfigParser 對象內存中的所有配置寫回到指定的文件中,覆蓋原有內容。所以,在進行寫入操作前,最好確保你已經加載了最新的配置文件內容,避免意外覆蓋掉未讀取的修改。在我看來,這種讀寫一體的能力讓 configparser 在很多小型到中型項目中都能發揮大作用,尤其是在需要用戶界面來調整后端配置的場景下,它能省去不少麻煩。

? 版權聲明
THE END
喜歡就支持一下吧
點贊13 分享