Python 模塊與包
本章學習知識點
- 模塊導入:import 模塊、from 模塊 import 函數、自定義模塊
- 常用標準庫:
- os/sys:系統操作(文件路徑、環境變量)
- datetime:時間處理(日期轉換、計時)
- json:JSON 數據解析與生成
- collections:高級數據結構(defaultdict、deque、Counter)
模塊與包是 Python 代碼模塊化、可維護性的核心,能讓你實現「代碼複用、功能拆分、第三方集成」。本手冊聚焦 模塊導入機制、自定義模塊與包,並深入講解高頻實用的標準庫(os/sys/datetime/json/collections)
一、模塊與包基礎
1.1 核心概念
-
模塊(Module):一個
.py文件就是一個模塊,包含變量、函數、類等代碼,可被其他文件導入使用(核心價值:代碼複用)。 -
包(Package):包含:
__init__.py文件的文件夾,用於組織多個相關模塊(核心價值:按功能拆分代碼,避免模塊名衝突)。- 注意:Python 3.3+ 支持「命名空間包」(無需
__init__.py),但推薦保留__init__.py用於初始化包、控制導入行為。
- 注意:Python 3.3+ 支持「命名空間包」(無需
1.2 模塊導入機制
-
Python 導入模塊時,會按以下順序查找模塊文件:
- 當前執行腳本所在目錄(優先);
- 系統環境變量
PYTHONPATH指定的目錄; - Python 安裝目錄下的標準庫目錄;
- 第三方庫目錄(如
site-packages)。
-
導入模塊的 4 種常用方式,需根據場景靈活選擇:
-
import 模塊名(導入整個模塊)-
語法:
import 模塊名 [as 別名] -
特點:導入整個模塊,通過「模塊名。屬性」訪問模塊內的函數 / 變量 / 類,避免命名衝突。
-
適用場景:模塊功能較多,需多次使用模塊內的不同屬性。
# 示例1:導入標準庫模塊(無別名) import math print(math.pi) # 訪問模塊變量 → 3.141592653589793 print(math.sqrt(16)) # 調用模塊函數 → 4.0 計算平方根比如25返回就是5 # 示例2:導入模塊並指定別名(簡化書寫) import datetime as dt current_time = dt.datetime.now() print(current_time) # 輸出當前時間 → 2025-11-27 10:00:00.123456
-
-
from 模塊名 import 屬性(導入模塊指定屬性)-
語法:
from 模塊名 import 函數/變量/類 [as 別名] -
特點:直接導入模塊內的指定屬性,可直接使用(無需加模塊名前綴),代碼更簡潔。
-
適用場景:僅需使用模塊內的少數幾個屬性。
# 示例1:導入模塊的單個屬性 from math import pi, sqrt print(pi) # 直接使用變量 → 3.141592653589793 print(sqrt(25)) # 直接調用函數 → 5.0 # 示例2:導入屬性並指定別名(避免命名衝突) from math import pow as power print(power(2, 3)) # 調用別名函數 → 8.0 # 示例3:導入模塊的所有屬性(不推薦,易衝突) from math import * print(sin(pi/2)) # 直接使用所有屬性 → 1.0 # 警告:若當前文件有同名函數/變量,會被覆蓋
-
-
from 包名 import 模塊(導入包內模塊)-
語法:
from 包名 import 模塊名 [as 別名]或from 包名.模塊名 import 屬性 -
特點:按包的層級結構導入模塊,適合大型項目的代碼組織。
# 假設項目結構如下: # my_project/ # main.py # utils/ # 包 # __init__.py # file_ops.py # 模塊(含 read_file 函數) # str_ops.py # 模塊(含 format_str 函數) # 在 main.py 中導入包內模塊 from utils import file_ops content = file_ops.read_file("test.txt") # 包.模塊.函數 # 直接導入包內模塊的屬性 from utils.str_ops import format_str formatted = format_str("hello") # 直接使用函數 # 導入包內模塊並指定別名 from utils import file_ops as fo content = fo.read_file("test.txt")
-
-
import 包名.模塊名(完整路徑導入)-
語法:
import 包名.模塊名 [as 別名] -
特點:明確指定模塊的完整路徑,可讀性強,避免同名模塊衝突。
# 延續上面的項目結構 import utils.file_ops content = utils.file_ops.read_file("test.txt") # 完整路徑導入並指定別名 import utils.str_ops as so formatted = so.format_str("hello")
-
-
1.3 自定義模塊
自定義模塊就是創建 .py 文件,編寫代碼後供其他文件導入,步驟如下:
-
創建模塊文件(
my_module.py)# my_module.py(自定義模塊) # 模塊變量 MODULE_NAME = "我的自定義模塊" VERSION = "1.0" # 模塊函數 def add(a, b): """兩數相加""" return a + b def multiply(a, b): """兩數相乘""" return a * b # 模塊類 class Calculator: def subtract(self, a, b): """兩數相減""" return a - b -
導入自定義模塊(在同一目錄下的
main.py)# main.py # 方式1:導入整個模塊 import my_module print(my_module.MODULE_NAME) # 訪問變量 → 我的自定義模塊 print(my_module.add(3, 5)) # 調用函數 → 8 calc = my_module.Calculator() print(calc.subtract(10, 4)) # 調用類方法 → 6 # 方式2:導入模塊指定屬性 from my_module import multiply, Calculator print(multiply(4, 5)) # → 20 calc2 = Calculator() print(calc2.subtract(20, 7)) # → 13 # 方式3:導入模塊並指定別名 import my_module as mm print(mm.VERSION) # → 1.0 -
注意事項:
-
模塊名遵循 PEP8 規範(小寫 + 下劃線,如
my_module),避免與標準庫 / 第三方庫模塊名衝突(如不要命名為os.py、json.py); -
若自定義模塊不在當前目錄,需將模塊所在目錄添加到
sys.path(見下文sys庫); -
模塊被導入時,其頂層代碼(如變量定義、函數定義、類定義)會被執行一次(可通過
if __name__ == "__main__":控制僅在直接運行模塊時執行的代碼)。# 優化 my_module.py:添加主程序入口 if __name__ == "__main__": # 僅當直接運行 my_module.py 時執行(導入時不執行) print("直接運行自定義模塊") print(add(2, 3)) # 測試函數
-
1.4 自定義包
自定義包用於組織多個相關模塊,步驟如下:
-
創建包結構
# 項目結構 my_project/ main.py tools/ # 包名 __init__.py # 包初始化文件(可空,也可用於導入配置) math_ops.py # 模塊1:數學運算 str_ops.py # 模塊2:字符串處理 -
編寫包內模塊代碼
# tools/math_ops.py def calculate_sum(n): """計算1到n的和""" return sum(range(1, n+1)) # tools/str_ops.py def reverse_str(s): """反轉字符串""" return s[::-1] -
(可選)優化
__init__.py(控制包導入行為)-
__init__.py可用於:1. 初始化包變量;2. 簡化導入路徑(通過__all__指定默認導入的模塊 / 屬性)。# tools/__init__.py # 包變量 PACKAGE_DESCRIPTION = "工具包:包含數學運算和字符串處理功能" # 指定 from tools import * 時導入的模塊(可選) __all__ = ["math_ops", "str_ops"] # 簡化導入:讓用户可直接 from tools import calculate_sum from .math_ops import calculate_sum from .str_ops import reverse_str
-
-
導入包並使用
# main.py # 方式1:導入包內模塊 from tools import math_ops, str_ops print(math_ops.calculate_sum(10)) # → 55 print(str_ops.reverse_str("hello")) # → olleh # 方式2:通過 __init__.py 簡化導入(直接導入屬性) from tools import calculate_sum, reverse_str print(calculate_sum(5)) # → 15 print(reverse_str("python")) # → nohtyp # 方式3:導入整個包 import tools print(tools.PACKAGE_DESCRIPTION) # 訪問包變量 print(tools.calculate_sum(8)) # 調用簡化導入的函數
二、常用標準庫實戰
Python 標準庫是內置的「工具集」,無需安裝即可使用,以下是開發中最常用的 5 個標準庫,覆蓋系統操作、時間處理、數據解析、高級數據結構等核心場景。
| 模塊大類 | 子模塊 / 核心功能 | 核心用途 | 關鍵特性 / 適用場景 |
|---|---|---|---|
| 時間處理模塊 | datetime | 時間運算(增減)、時間字段修改、高精度時間獲取 | 比 time 更直觀,支持 timedelta 時間差計算 |
| 文件與目錄操作模塊 | os | 目錄增刪、路徑處理、系統環境獲取、文件屬性查看 | 跨系統路徑兼容,基礎文件 / 目錄管理 |
| 系統交互模塊 | sys | 獲取 Python 解釋器信息、命令行參數處理、程序退出控制 | 命令行工具開發、系統參數獲取 |
| 數據序列化模塊 | json | 跨語言數據序列化 / 反序列化,支持基礎數據類型 | 多語言交互、接口數據傳輸 |
| 數據結構擴展模塊 | collections | 提供高性能專用數據結構(Counter、defaultdict、OrderedDict、deque 等) | 彌補內置數據結構不足,提升開發效率 |
2.1、sys 庫
sys 庫用於與 Python 解釋器本身交互,核心功能包括「命令行參數獲取、系統路徑配置、退出程序」等。
-
核心功能與方法
方法 / 屬性 功能描述 示例 sys.argv獲取命令行參數(列表,第一個元素是腳本名) 運行 python main.py 10 20→sys.argv → ["main.py", "10", "20"]sys.pathPython 模塊搜索路徑列表(可動態添加) print(sys.path) → [當前目錄, 標準庫目錄, ...]sys.version獲取 Python 版本信息 print(sys.version) → 3.9.7 (default, ...)sys.platform獲取操作系統平台 print(sys.platform) → linux/win32/darwin(Mac)sys.exit(code=0)退出程序(code=0 表示正常退出,非 0 表示異常) sys.exit(1)(異常退出)sys.stdin標準輸入流(如讀取用户輸入) line = sys.stdin.readline()sys.stdout標準輸出流(如打印內容) sys.stdout.write("Hello") -
示例
import sys # 1. 解析命令行參數(實現簡易計算器) print("命令行參數:", sys.argv) if len(sys.argv) != 4: print("用法:python main.py <操作符> <數字1> <數字2>") print("示例:python main.py add 10 20") sys.exit(1) # 異常退出(非 0 狀態碼) op = sys.argv[1] num1 = float(sys.argv[2]) num2 = float(sys.argv[3]) if op == "add": print(f"{num1} + {num2} = {num1 + num2}") elif op == "sub": print(f"{num1} - {num2} = {num1 - num2}") elif op == "mul": print(f"{num1} × {num2} = {num1 * num2}") elif op == "div": if num2 == 0: print("錯誤:除數不能為 0") sys.exit(1) print(f"{num1} ÷ {num2} = {num1 / num2:.2f}") else: print("支持的操作符:add/sub/mul/div") sys.exit(1) ############ 寫法2 ############ import sys print(sys.argv) if len(sys.argv) != 4 or len(sys.argv) >= 5: print("用法:python main.py <操作符[add,sub,mul]> <數字1> <數字2>") print("示例:python main.py add 10 20") sys.exit(1) # 異常退出(非 0 狀態碼) # 如果不去掉第1個 控制枱四個參數 打印['絕對路徑/名稱.py', 'add', '10', '20'] operator = sys.argv[1::] def args(*args): num1=float(args[1]) num2=float(args[2]) if args[0]=='add': print(num1+num2) elif args[0]=='sub': print(num1-num2) elif args[0]=='mul': print(num1*num2) else: print("請輸入正確的操作符") sys.exit(1) args(*operator) # 2. 動態添加模塊搜索路徑(導入非當前目錄的自定義模塊) # 假設自定義模塊在 /home/user/my_modules 目錄下 custom_module_dir = "/home/user/my_modules" if custom_module_dir not in sys.path: sys.path.append(custom_module_dir) # 添加到搜索路徑 print(f"已添加模塊路徑:{custom_module_dir}") # 之後即可導入該目錄下的模塊 # import my_custom_module
2.1、os 庫
os 庫提供與操作系統交互的接口,核心用於「文件路徑操作、目錄管理、系統命令執行」,是文件處理的基礎。
-
核心功能與方法
方法 / 屬性 功能描述 示例 os.getcwd()獲取當前工作目錄 print(os.getcwd()) → /home/user/projectos.chdir(path)切換工作目錄 os.chdir("/home/user")os.listdir(path=".")列出目錄下的所有文件 / 子目錄 os.listdir("./tools") → ["math_ops.py", ...]os.mkdir(path)創建單個目錄(父目錄必須存在) os.mkdir("./data")os.makedirs(path)遞歸創建目錄(父目錄不存在則自動創建) os.makedirs("./data/logs")os.remove(path)刪除文件 os.remove("./test.txt")os.rmdir(path)刪除空目錄 os.rmdir("./data")os.removedirs(path)遞歸刪除空目錄 os.removedirs("./data/logs")os.rename(old, new)重命名文件 / 目錄 os.rename("old.txt", "new.txt")os.path.exists(path)判斷路徑是否存在(文件 / 目錄) os.path.exists("./tools") → Trueos.path.isfile(path)判斷是否為文件 os.path.isfile("./main.py") → Trueos.path.isdir(path)判斷是否為目錄 os.path.isdir("./tools") → Trueos.path.join(p1, p2, ...)拼接路徑(自動適配系統分隔符) os.path.join("./data", "logs") → ./data/logsos.path.abspath(path)獲取路徑的絕對路徑 os.path.abspath("./main.py") → /home/user/project/main.pyos.path.splitext(path)分割文件名和擴展名 os.path.splitext("test.txt") → ("test", ".txt") -
示例
import os # 1. 路徑拼接(跨平台兼容) # 錯誤方式:直接用 + 拼接(Windows 用 \,Linux 用 /,易出錯) # bad_path = "./data" + "/logs" # 正確方式:用 os.path.join data_dir = os.path.join(os.getcwd(), "data") log_dir = os.path.join(data_dir, "logs") print("日誌目錄路徑:", log_dir) # 2. 目錄創建(不存在則創建) if not os.path.exists(log_dir): os.makedirs(log_dir) # 遞歸創建 print(f"目錄 {log_dir} 創建成功") else: print(f"目錄 {log_dir} 已存在") # 3. 遍歷目錄下的所有 .py 文件 project_dir = os.getcwd() py_files = [] for root, dirs, files in os.walk(project_dir): # 遞歸遍歷目錄 for file in files: if file.endswith(".py"): # 篩選 .py 文件 file_path = os.path.join(root, file) py_files.append(file_path) print(f"\n項目中所有 .py 文件(共 {len(py_files)} 個):") for path in py_files: print(path) # 4. 文件重命名(批量修改後綴) current_path=os.path.dirname(os.path.abspath(__file__)) file_list=["file1.txt","file2.txt","file3.txt"] for file in file_list: get_check_file_path=os.path.join(current_path,"bac") # 多用os.getpwd()看一下當前路徑 name,type=os.path.splitext(file) # "filex",".txt" newe_nam=name+".md" # 改為 .md 後綴 os.rename(os.path.join(get_check_file_path,file), os.path.join(get_check_file_path,newe_nam)) print(f"舊文件:{file} --> 新文件:{os.path.join(get_check_file_path,newe_nam)}") -
獲取「腳本文件所在目錄」
# 當前在【D:\docker\miscellaneous\python\模塊與包\模塊使用】下使用os.getcwd(),查看只到 D:\docker\miscellaneous\python 怎麼獲取到 D:\docker\miscellaneous\python\模塊與包\模塊使用 # # 獲取當前腳本文件的絕對路徑 script_path = os.path.abspath(__file__) # 獲取腳本文件所在的目錄(即模塊使用目錄) script_dir = os.path.dirname(script_path) os.chdir(os.path.dirname(os.path.abspath(__file__))) print(os.getcwd())
2.3、datetime 庫
datetime 庫是 Python 處理時間的核心庫,支持「日期轉換、時間計算、格式化輸出」,比 time 庫更強大、易用。
-
核心功能與方法
類 / 方法 功能描述 示例 datetime.datetime.now()獲取當前本地時間(datetime 對象) dt.now() → 2025-11-27 10:30:00.123456datetime.date.today()獲取當前日期(date 對象) date.today() → 2025-11-27datetime.datetime.strptime(date_str, format)字符串轉 datetime 對象 strptime("2025-11-27", "%Y-%m-%d") → 2025-11-27 00:00:00datetime.datetime.strftime(format)datetime 對象轉字符串 dt.strftime("%Y-%m-%d %H:%M:%S") → "2025-11-27 10:30:00"datetime.timedelta(days/hours/minutes/seconds)時間間隔對象(用於時間計算) timedelta(days=1) → 1 天dt1 - dt2兩個 datetime 對象相減,返回 timedelta dt.now() - dt(2025,1,1) → 330 天...dt + timedeltadatetime 對象加時間間隔,返回新 datetime dt.now() + timedelta(hours=3) → 3 小時後timestamp 將時間轉換為時間戳 fromtimestamp 將時間戳轉換為時間 -
時間格式化符號(常用):
%Y:4 位年份(如 2025)%m:2 位月份(01-12)%d:2 位日期(01-31)%H:24 小時制(00-23)%M:分鐘(00-59)%S:秒(00-59)%w:星期(0-6,0 是週日)
-
-
示例
from datetime import datetime, date, timedelta # 1. 獲取當前時間與日期 current_dt = datetime.now() # 含時分秒毫秒 current_date = date.today() # 僅日期 print("當前完整時間:", current_dt) print("當前日期:", current_date) print("當前小時:", current_dt.hour) print("當前星期:", current_dt.weekday()) # 0=週一,6=週日 # 2. 時間格式化(datetime → 字符串) formatted_dt = current_dt.strftime("%Y-%m-%d %H:%M:%S") print("格式化時間:", formatted_dt) # → 2025-11-27 10:35:22 # 3. 字符串轉時間(字符串 → datetime) time_str = "2025-12-01 12:00:00" parsed_dt = datetime.strptime(time_str, "%Y-%m-%d %H:%M:%S") print("解析後的時間:", parsed_dt) print("解析後的年份:", parsed_dt.year) # 4. 時間計算(加減時間間隔) # 3天后的時間 three_days_later = current_dt + timedelta(days=3) print("3天后:", three_days_later.strftime("%Y-%m-%d")) # 2小時30分鐘前的時間 two_hours_ago = current_dt - timedelta(hours=2, minutes=30) print("2小時30分鐘前:", two_hours_ago.strftime("%H:%M:%S")) # 計算兩個日期的差值 date1 = date(2025, 1, 1) date2 = date(2025, 11, 27) delta = date2 - date1 print("兩個日期相差:", delta.days, "天") # 5. 函數執行計時(統計代碼運行時間) def test_func(): sum(range(1, 1000000)) start_time = datetime.now() test_func() end_time = datetime.now() duration = (end_time - start_time).total_seconds() # 耗時(秒) print(f"函數執行耗時:{duration:.4f} 秒") # 時間戳轉換 print(dt.datetime.now().timestamp()) # 1764573102.217211 print(dt.datetime.fromtimestamp(1764573102.217211))
2.4、json 庫
JSON 是前後端交互、數據存儲的常用格式,json 庫支持「JSON 字符串 → Python 對象」(解析)和「Python 對象 → JSON 字符串」(生成)。
-
核心映射關係(Python ↔ JSON)
Python 類型 JSON 類型 dict object(對象) list/tuple array(數組) str string(字符串) int/float number(數字) True true False false None null -
核心方法
功能描述 方法 示例 Python 對象 → JSON 字符串(indent 格式化輸出) json.dumps(obj, ensure_ascii=False, indent=2)dumps({"name":"小明"}, ensure_ascii=False) → '{"name":"小明"}'JSON 字符串 → Python 對象 json.loads(json_str)loads('{"name":"小明"}') → {"name":"小明"}Python 對象 → JSON 文件(fp 是文件對象) json.dump(obj, fp, ensure_ascii=False, indent=2)dump(data, open("data.json", "w"))JSON 文件 → Python 對象 json.load(fp)load(open("data.json", "r")) → data -
實戰
import json # 1. Python 對象 → JSON 字符串(生成) data = { "name": "小明", "age": 20, "gender": "男", "is_student": True, "hobbies": ["籃球", "音樂", "旅行"], "address": { "city": "上海", "district": "浦東新區" }, "score": None } # dumps 生成 JSON 字符串(ensure_ascii=False 保留中文,indent=2 格式化) json_str = json.dumps(data, ensure_ascii=False, indent=2) print("JSON 字符串:") print(json_str) # 2. JSON 字符串 → Python 對象(解析) parsed_data = json.loads(json_str) print("\n解析後的 Python 對象:") print(type(parsed_data)) # → <class 'dict'> print("姓名:", parsed_data["name"]) print("愛好:", parsed_data["hobbies"][0]) # 3. Python 對象 → JSON 文件(寫入文件) current_dir= os.path.dirname(os.path.abspath(__file__)) with open(f"{os.path.join(current_dir, 'data.json')}", 'w', encoding='utf-8') as f: json.dump(data, f, ensure_ascii=False, indent=2) print(f"數據已保存到 {current_dir}") # 4. JSON 文件 → Python 對象(讀取文件) with open(f"{os.path.join(current_dir, 'data.json')}", 'r', encoding='utf-8') as f: loaded_data = json.load(f) print("\n從文件讀取的 JSON 數據:") print(loaded_data["address"]["city"]) # → 上海 # 5. 處理複雜 JSON 數據(嵌套解析) complex_json = ''' { "code": 200, "message": "success", "data": { "total": 2, "users": [ {"id": 1, "name": "小紅", "age": 18}, {"id": 2, "name": "小李", "age": 19} ] } } ''' result = json.loads(complex_json) if result["code"] == 200: users = result["data"]["users"] print("\n用户列表:") for user in users: print(f"ID:{user['id']},姓名:{user['name']}")
2.5、collections
collections 庫提供了比內置數據結構(list/dict/set/tuple)更強大的擴展類型,解決了內置結構的諸多痛點(如字典缺省值、有序字典、計數統計等)。
-
核心類型與用法
-
defaultdict:帶默認值的字典-
痛點:內置
dict訪問不存在的鍵會報錯,需用get(key, default)或判斷鍵是否存在; -
解決方案:
defaultdict初始化時指定「默認值類型 / 函數」,訪問不存在的鍵時自動生成默認值。from collections import defaultdict # 示例1:默認值為列表(用於分組) student_scores = [ ("小明", "數學", 90), ("小明", "英語", 85), ("小紅", "數學", 95), ("小紅", "英語", 88) ] # defaultdict(list):不存在的鍵默認生成空列表 score_dict = defaultdict(list) for name, subject, score in student_scores: score_dict[name].append((subject, score)) # 無需判斷 name 是否存在 print("學生成績分組:") for name, scores in score_dict.items(): print(f"{name}:{scores}") # 輸出: # 小明:[('數學', 90), ('英語', 85)] # 小紅:[('數學', 95), ('英語', 88)] # 示例2:默認值為整數(用於計數) word_count = defaultdict(int) words = ["apple", "banana", "apple", "cherry", "banana", "apple"] for word in words: # defaultdict(<class 'int'>, {'apple': 3, 'banana': 2, 'cherry': 1}) word_count[word] += 1 # 不存在的鍵默認值為 0,直接累加 print("\n單詞計數:", dict(word_count)) # → {'apple':3, 'banana':2, 'cherry':1}
-
-
-
Counter:計數統計工具-
功能:專門用於「可迭代對象的元素計數」,比
defaultdict(int)更簡潔、功能更強。from collections import Counter # 示例1:字符串字符計數 s = "abracadabra" char_count = Counter(s) print("字符計數:", char_count) # → Counter({'a':5, 'b':2, 'r':2, 'c':1, 'd':1}) # 示例2:列表元素計數 nums = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4] num_count = Counter(nums) print("數字計數:", num_count) # → Counter({4:4, 3:3, 2:2, 1:1}) # 示例3:獲取Top N元素(常用場景) top2 = num_count.most_common(2) # 獲取出現次數最多的2個元素 print("出現次數最多的2個數字:", top2) # → [(4,4), (3,3)] # 示例4:計數器運算(交集/並集/差集) c1 = Counter([1,2,3,3]) c2 = Counter([3,4,4,5]) print("交集(共同元素的最小計數):", c1 & c2) # → Counter({3:1}) print("並集(所有元素的最大計數):", c1 | c2) # → Counter({1:1,2:1,3:2,4:2,5:1}) print("差集(c1有但c2沒有的元素):", c1 - c2) # → Counter({1:1,2:1,3:1})
-
-
deque:雙端隊列(高效增刪)-
痛點:內置
list是動態數組,頭部增刪元素(insert(0)/pop(0))效率低(時間複雜度 O (n)); -
解決方案:
deque是雙端隊列,頭部 / 尾部增刪元素效率極高(時間複雜度 O (1)),支持最大長度限制。from collections import deque # 示例1:基礎操作(頭部/尾部增刪) dq = deque([1, 2, 3]) dq.append(4) # 尾部添加 → deque([1,2,3,4]) dq.appendleft(0) # 頭部添加 → deque([0,1,2,3,4]) dq.pop() # 尾部刪除 → 4 → deque([0,1,2,3]) dq.popleft() # 頭部刪除 → 0 → deque([1,2,3]) print("雙端隊列:", dq) # 示例2:最大長度限制(超出則自動刪除另一端元素) limited_dq = deque(maxlen=3) # 最大長度3 limited_dq.append(1) limited_dq.append(2) limited_dq.append(3) print("限制長度3的隊列:", limited_dq) # → deque([1,2,3], maxlen=3) limited_dq.append(4) # 超出長度,刪除頭部元素1 print("添加4後:", limited_dq) # → deque([2,3,4], maxlen=3) # 示例3:高效滑動窗口(常用場景) def sliding_window(nums, k): dq = deque() result = [] for i, num in enumerate(nums): # 移除窗口外的元素(索引小於 i-k+1 的元素) while dq and dq[0] < i - k + 1: dq.popleft() # 移除隊列中比當前元素小的元素(維護隊列遞減) while dq and nums[dq[-1]] < num: dq.pop() dq.append(i) # 窗口大小達到 k 後,記錄最大值(隊列頭部) if i >= k - 1: result.append(nums[dq[0]]) return result nums = [1, 3, -1, -3, 5, 3, 6, 7] k = 3 print("滑動窗口最大值:", sliding_window(nums, k)) # → [3,3,5,5,6,7]
-
三、綜合實戰
-
日誌收集工具(os+datetime+json+collections)
""" 功能:收集指定目錄下的日誌文件,解析錯誤日誌,統計錯誤類型並保存為 JSON 報告 技術點:os 目錄遍歷、datetime 時間處理、json 數據生成、collections.Counter 計數 """ import os import json from datetime import datetime from collections import Counter def collect_error_logs(log_dir, output_file): # 1. 驗證日誌目錄是否存在 if not os.path.isdir(log_dir): print(f"錯誤:目錄 {log_dir} 不存在") return # 2. 遍歷目錄下的所有 .log 文件 error_records = [] error_types = [] for root, dirs, files in os.walk(log_dir): for file in files: if file.endswith(".log"): log_file_path = os.path.join(root, file) print(f"正在解析日誌文件:{log_file_path}") # 3. 讀取日誌文件,篩選錯誤日誌(假設錯誤日誌以 ERROR: 開頭) with open(log_file_path, "r", encoding="utf-8", errors="ignore") as f: for line_num, line in enumerate(f, start=1): line = line.strip() if line.startswith("ERROR:"): # 解析日誌時間(假設日誌格式:[2025-11-27 10:00:00] ERROR: ...) if "[" in line and "]" in line: time_str = line.split("]")[0].strip("[") try: log_time = datetime.strptime(time_str, "%Y-%m-%d %H:%M:%S") except ValueError: log_time = None else: log_time = None # 記錄錯誤詳情 error_info = { "file": log_file_path, "line": line_num, "time": log_time.strftime("%Y-%m-%d %H:%M:%S") if log_time else "未知", "message": line } error_records.append(error_info) # 提取錯誤類型(假設錯誤格式:ERROR: 類型: 描述) if ": " in line[6:]: # 跳過 "ERROR:" 前綴 error_type = line[6:].split(": ")[0].strip() error_types.append(error_type) # 4. 統計錯誤類型 error_count = Counter(error_types) if error_types else {} # 5. 生成報告數據 report = { "report_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S"), "log_dir": log_dir, "total_error_count": len(error_records), "error_type_statistics": dict(error_count), "error_details": error_records } # 6. 保存報告為 JSON 文件 with open(output_file, "w", encoding="utf-8") as f: json.dump(report, f, ensure_ascii=False, indent=2) print(f"\n日誌收集完成!共發現 {len(error_records)} 條錯誤,報告已保存至:{output_file}") # 執行日誌收集 if __name__ == "__main__": # 日誌目錄(可替換為實際目錄) target_log_dir = "./logs" # 輸出報告文件 output_json = "error_report.json" # 執行收集 collect_error_logs(target_log_dir, output_json)
四、易錯點總結
- 模塊命名衝突:自定義模塊名與標準庫(如
os.py、json.py)或第三方庫同名,導致導入錯誤(解決方案:修改自定義模塊名); - 路徑拼接錯誤:直接用
+拼接路徑(如"./data" + "/logs"),不兼容 Windows/Linux 系統(解決方案:用os.path.join); - JSON 中文亂碼:
json.dump時未指定ensure_ascii=False,導致中文被轉義為 Unicode 編碼(解決方案:添加ensure_ascii=False); datetime格式化錯誤:混用格式化符號(如%Y寫成%y,%H寫成%h),導致解析 / 格式化失敗(解決方案:熟記常用格式化符號);deque與list混淆:用list進行頭部高頻增刪操作,導致效率低下(解決方案:改用collections.deque);- 模塊導入路徑問題:自定義模塊不在當前目錄,且未添加到
sys.path,導致導入失敗(解決方案:sys.path.append(模塊目錄)); defaultdict默認值類型錯誤:初始化時指定錯誤的默認值類型(如需要列表卻指定int),導致後續操作報錯(解決方案:根據場景選擇默認值類型)。
通過本手冊的學習,你已經掌握了 Python 模塊與包的核心用法,以及高頻標準庫的實戰技巧。這些知識點是 Python 開發的基礎,後續學習 Web 框架(如 Flask/Django)、數據分析(如 Pandas)、自動化測試等內容時,都會基於模塊與包的思想擴展。建議多結合實際項目練習(如工具腳本開發、數據處理),加深對模塊複用、代碼組織的理解,提高開發效率!