Python開(kāi)發(fā)中最常見(jiàn)的錯(cuò)誤大全及解決方法
引言
Python 以“簡(jiǎn)潔易讀”著稱,但即便是經(jīng)驗(yàn)豐富的開(kāi)發(fā)者,也常被各種錯(cuò)誤搞得焦頭爛額。這些錯(cuò)誤不僅影響開(kāi)發(fā)效率,還可能潛伏在生產(chǎn)環(huán)境中引發(fā)嚴(yán)重故障。
本文系統(tǒng)梳理了 Python 中最常見(jiàn)的錯(cuò)誤類型,并特別深入解析了 JSON 相關(guān)錯(cuò)誤——這是 Web 開(kāi)發(fā)、API 調(diào)用和數(shù)據(jù)處理中最頻繁出現(xiàn)的問(wèn)題之一。每類錯(cuò)誤都配有 真實(shí)示例 + 原理解釋 + 解決方案,助你快速排錯(cuò)、寫出健壯代碼。
一、錯(cuò)誤分類概覽
Python 錯(cuò)誤主要分為三類:
- 語(yǔ)法錯(cuò)誤(SyntaxError) :代碼不符合 Python 語(yǔ)法規(guī)則,解釋器直接拒絕運(yùn)行。
- 運(yùn)行時(shí)異常(Exceptions) :程序能啟動(dòng),但在執(zhí)行過(guò)程中因邏輯或環(huán)境問(wèn)題崩潰。
- 邏輯錯(cuò)誤(Logic Errors) :代碼能運(yùn)行且不報(bào)錯(cuò),但結(jié)果不符合預(yù)期(最難調(diào)試)。
我們重點(diǎn)討論前兩類,并加入 JSON 專項(xiàng)章節(jié)。
二、語(yǔ)法錯(cuò)誤(SyntaxError)
這類錯(cuò)誤在保存或運(yùn)行腳本時(shí)立即暴露。
常見(jiàn)場(chǎng)景:
- 缺少冒號(hào)
:(if,for,def后必須加) - 括號(hào)/引號(hào)不匹配
- 錯(cuò)誤縮進(jìn)(混用空格與 Tab)
# ? 典型錯(cuò)誤
if x > 0
print("positive") # SyntaxError: invalid syntax
# ? 正確寫法
if x > 0:
print("positive")
建議:使用支持語(yǔ)法高亮和括號(hào)匹配的編輯器(如 VS Code、PyCharm)。
三、運(yùn)行時(shí)異常(Exceptions)
1. NameError:變量未定義
print(username) # NameError: name 'username' is not defined
解決:確保變量已賦值,注意作用域。
2. AttributeError:對(duì)象無(wú)此屬性
[].push(1) # AttributeError: 'list' object has no attribute 'push'
解決:查官方文檔,確認(rèn)方法名(如 list.append())。
3. IndexError / KeyError:越界訪問(wèn)
d = {"name": "Alice"}
print(d["age"]) # KeyError: 'age'
安全訪問(wèn):
d.get("age", "未知") # 推薦
# 或
if "age" in d: ...
4. TypeError:類型不匹配
"5" + 3 # TypeError: can only concatenate str (not "int") to str
解決:顯式轉(zhuǎn)換類型,如 int("5") + 3。
5. ValueError:值合法但不符合要求
int("abc") # ValueError: invalid literal for int()
防御性編程:
try:
num = int(user_input)
except ValueError:
print("請(qǐng)輸入有效數(shù)字")
6. ZeroDivisionError:除零錯(cuò)誤
10 / 0 # ZeroDivisionError
檢查分母:
if denominator != 0:
result = numerator / denominator
7. FileNotFoundError:文件不存在
open("missing.txt") # FileNotFoundError
安全打開(kāi):
import os
if os.path.exists("file.txt"):
with open("file.txt") as f: ...
8. ModuleNotFoundError:模塊未安裝
import requests # ModuleNotFoundError(若未安裝)
解決:
pip install requests
四、經(jīng)典邏輯陷阱
可變默認(rèn)參數(shù)(Mutable Default Argument)
# ? 危險(xiǎn)!
def add(item, lst=[]):
lst.append(item)
return lst
print(add(1)) # [1]
print(add(2)) # [1, 2] ← 意外共享!
# ? 正確
def add(item, lst=None):
if lst is None:
lst = []
lst.append(item)
return lst
黃金法則:永遠(yuǎn)不要用 list、dict、set 等可變對(duì)象作為函數(shù)默認(rèn)參數(shù)!
五、JSON 專項(xiàng):最常被忽視的錯(cuò)誤源
在 API 開(kāi)發(fā)、配置文件讀取、前后端通信中,JSON 是數(shù)據(jù)交換的通用語(yǔ)言。但處理不當(dāng)極易出錯(cuò)。
1.json.JSONDecodeError:JSON 格式非法
這是 最常見(jiàn) 的 JSON 錯(cuò)誤,通常由以下原因引起:
場(chǎng)景 1:字符串不是合法 JSON
import json
data = "{'name': 'Alice'}" # 注意:用了單引號(hào)!
json.loads(data) # JSONDecodeError: Expecting property name enclosed in double quotes
原因:JSON 標(biāo)準(zhǔn)要求 鍵和字符串必須用雙引號(hào) " ,單引號(hào)無(wú)效。
解決:
- 確保數(shù)據(jù)源輸出標(biāo)準(zhǔn) JSON(如后端用
json.dumps()) - 若必須解析非標(biāo)準(zhǔn)字符串,可先替換:
data = data.replace("'", '"')
場(chǎng)景 2:末尾多余逗號(hào)
data = '{"name": "Alice", "age": 30,}' # 末尾逗號(hào)
json.loads(data) # JSONDecodeError
解決:使用在線 JSON 校驗(yàn)工具(如 jsonlint.com)驗(yàn)證。
場(chǎng)景 3:響應(yīng)體為空或 HTML
# 模擬請(qǐng)求返回 404 頁(yè)面(HTML) response_text = "<html>Not Found</html>" json.loads(response_text) # JSONDecodeError
防御性處理:
import json
import requests
resp = requests.get("https://api.example.com/data")
try:
data = resp.json() # requests 內(nèi)部調(diào)用 json.loads()
except json.JSONDecodeError:
print("響應(yīng)不是 JSON!狀態(tài)碼:", resp.status_code)
print("原始內(nèi)容:", resp.text[:200])
2.TypeError: Object of type xxx is not JSON serializable
當(dāng)你嘗試把 非 JSON 支持的類型 序列化時(shí)發(fā)生:
import json
from datetime import datetime
data = {"time": datetime.now()}
json.dumps(data) # TypeError: Object of type datetime is not JSON serializable
解決方法:
方法 1:自定義default函數(shù)
def json_serializer(obj):
if isinstance(obj, datetime):
return obj.isoformat()
raise TypeError(f"Type {type(obj)} not serializable")
json.dumps(data, default=json_serializer)
方法 2:提前轉(zhuǎn)換
data = {"time": datetime.now().isoformat()}
json.dumps(data) # OK
方法 3:使用第三方庫(kù)(如orjson、ujson)支持更多類型
3. 中文亂碼問(wèn)題(編碼錯(cuò)誤)
# 寫入文件
with open("config.json", "w") as f:
json.dump({"消息": "你好"}, f)
# 讀取時(shí)可能亂碼(尤其在 Windows)
解決:顯式指定 UTF-8 編碼
# 寫入
with open("config.json", "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False) # 關(guān)鍵:ensure_ascii=False
# 讀取
with open("config.json", "r", encoding="utf-8") as f:
data = json.load(f)
兩個(gè)關(guān)鍵參數(shù):
encoding="utf-8":確保文件以 UTF-8 讀寫ensure_ascii=False:允許輸出中文而非\u4f60\u597d
六、最佳實(shí)踐:如何避免和快速定位錯(cuò)誤?
1. 使用try...except精準(zhǔn)捕獲
try:
data = json.loads(api_response)
except json.JSONDecodeError as e:
logger.error(f"JSON 解析失敗: {e.msg} at line {e.lineno}")
except Exception as e:
logger.error(f"未知錯(cuò)誤: {e}")
2. 啟用類型提示 + mypy
def parse_user(data: str) -> dict:
return json.loads(data) # mypy 可檢查返回類型
3. 單元測(cè)試覆蓋異常路徑
def test_invalid_json():
with pytest.raises(json.JSONDecodeError):
parse_user("{'invalid': json}")
4. 日志記錄原始數(shù)據(jù)
當(dāng) JSON 解析失敗時(shí),務(wù)必記錄原始字符串,便于復(fù)現(xiàn)問(wèn)題。
七、總結(jié)
| 錯(cuò)誤類型 | 高頻場(chǎng)景 | 防御策略 |
|---|---|---|
SyntaxError | 縮進(jìn)、冒號(hào)、括號(hào) | 使用智能 IDE |
NameError | 變量未定義 | 檢查拼寫與作用域 |
JSONDecodeError | 非標(biāo)準(zhǔn) JSON、空響應(yīng) | 校驗(yàn) + try-except + 記錄原始數(shù)據(jù) |
TypeError(序列化) | datetime、自定義對(duì)象 | 自定義 default 或預(yù)轉(zhuǎn)換 |
| 可變默認(rèn)參數(shù) | 函數(shù)默認(rèn)值為 list/dict | 用 None 代替 |
記住:
“錯(cuò)誤不是敵人,而是你代碼的反饋。”
學(xué)會(huì)閱讀錯(cuò)誤信息(尤其是 traceback 和JSONDecodeError的lineno),是成為高效 Python 開(kāi)發(fā)者的關(guān)鍵一步。
以上就是Python開(kāi)發(fā)中最常見(jiàn)的錯(cuò)誤大全及解決方法的詳細(xì)內(nèi)容,更多關(guān)于Python最常見(jiàn)的錯(cuò)誤大全的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
python實(shí)現(xiàn)兩個(gè)字典合并,兩個(gè)list合并
今天小編就為大家分享一篇python實(shí)現(xiàn)兩個(gè)字典合并,兩個(gè)list合并,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-12-12
在SAE上部署Python的Django框架的一些問(wèn)題匯總
這篇文章主要介紹了在SAE上部署Python的Django框架的一些問(wèn)題匯總,SAE是新浪的一個(gè)在線APP部署平臺(tái),并且對(duì)Python應(yīng)用提供相關(guān)支持,需要的朋友可以參考下2015-05-05
完美解決keras保存好的model不能成功加載問(wèn)題
這篇文章主要介紹了完美解決keras保存好的model不能成功加載問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-06-06
python3+pyqt5+itchat微信定時(shí)發(fā)送消息的方法
今天小編就為大家分享一篇python3+pyqt5+itchat微信定時(shí)發(fā)送消息的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-02-02
django 解決擴(kuò)展自帶User表遇到的問(wèn)題
這篇文章主要介紹了django 解決擴(kuò)展自帶User表遇到的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-05-05
Python通過(guò)RabbitMQ服務(wù)器實(shí)現(xiàn)交換機(jī)功能的實(shí)例教程
RabbitMQ是一個(gè)基于消息隊(duì)列的服務(wù)器程序,Python可以通過(guò)Pika庫(kù)來(lái)驅(qū)動(dòng)它,這里我們將來(lái)看一個(gè)Python通過(guò)RabbitMQ服務(wù)器實(shí)現(xiàn)交換機(jī)功能的實(shí)例教程:2016-06-06
Python類中__init__()?和self的詳細(xì)解析
self和__init__的語(yǔ)法學(xué)過(guò)Python的都清楚,但是靠死記硬背來(lái)迫使自己理解并不是個(gè)好辦法,下面這篇文章主要給大家介紹了關(guān)于Python類中__init__()?和self的相關(guān)資料,需要的朋友可以參考下2022-12-12

