關于Python:3. Python標準庫和常用模塊

1. os 和 sys(系統編程基礎)

這兩個模塊是進行系統層面操作(如文件管理、路徑處理、環境變量訪問等)必不可少的工具。

os 模塊

os 主要是用于與操作系統交互的,比如:

  • 文件和目錄操作

  • 獲取系統信息

  • 運行系統命令

  • 管理環境變量

可以理解為:讓你的 Python 代碼能夠操作"文件系統"、"目錄結構"、"系統指令"等資源。

路徑操作:

import osprint(os.getcwd())         # 獲取當前工作目錄
os.chdir('./tmp')            # 改變當前工作目錄
print(os.listdir('.'))      # 列出當前目錄下的所有文件和文件夾 當前工作目錄已經是 ./tmp

文件/文件夾操作:

os.mkdir('testdir')         # 創建文件夾
os.rmdir('testdir')         # 刪除空文件夾
os.remove('file.txt')       # 刪除文件
os.rename('old.txt', 'new.txt')  # 重命名文件或文件夾

路徑拼接與判斷:

path = os.path.join('folder', 'file.txt')  # 拼接路徑(自動處理/或\問題)
print(os.path.exists(path))                # 檢查路徑是否存在
print(os.path.isfile(path))                # 是否是文件
print(os.path.isdir(path))                 # 是否是目錄

執行系統命令:

# 獲取環境變量
home = os.environ.get('HOME')
print(home)os.system('ls -l')           # 運行一個系統命令(同步阻塞)

(注:更推薦用 subprocess,因為更安全、靈活)

sys 模塊

sys 主要是用于跟 Python 解釋器交互,比如:

  • 讀取命令行參數

  • 退出程序

  • 獲取 Python 環境信息

  • 修改模塊搜索路徑

可以理解為:讓你的程序能控制/了解運行時自身的狀態。

命令行參數:

import sysprint(sys.argv)             # 獲取命令行參數,列表,第一個是程序本身# 例如命令行運行:
# python test.py arg1 arg2
# sys.argv 結果就是:
# ['test.py', 'arg1', 'arg2']

退出程序:

sys.exit(0)                 # 正常退出
sys.exit(1)                 # 異常退出

Python 版本信息:

print(sys.version)          # 打印Python版本
print(sys.platform)         # 當前系統平臺:'win32', 'linux', 'darwin'(Mac)

修改模塊搜索路徑:

import sys# 加了之后,Python在**import 模塊**時,除了默認的系統路徑,還會去你指定的新路徑里找模塊。
sys.path.append('/path/to/your/module')    # 動態添加模塊搜索路徑

(比如項目中的一些自定義模塊,需要臨時導入)

實際綜合例子

寫一個 Python 腳本,它可以根據命令行傳參,創建一個目錄并進入:

import os
import sysdef create_and_enter_dir(dirname):if not os.path.exists(dirname):os.mkdir(dirname)print(f"Directory '{dirname}' created.")else:print(f"Directory '{dirname}' already exists.")os.chdir(dirname)print(f"Now in directory: {os.getcwd()}")if __name__ == "__main__":if len(sys.argv) != 2:print("Usage: python script.py <dirname>")sys.exit(1)create_and_enter_dir(sys.argv[1])

這樣可以:

python script.py myfolder

自動創建并進入 myfolder


2. datetime(時間處理)

用于處理日期和時間的模塊,常用于日志、時間戳生成、時間間隔計算等。

獲取當前時間:

import datetimenow = datetime.datetime.now()
print(now)  # 比如輸出:2025-04-29 15:30:42.123456

?如果只要日期

today = datetime.date.today()
print(today)  # 比如:2025-04-29

創建指定時間:

d = datetime.datetime(2025, 5, 1, 12, 30, 45)  # 年, 月, 日, 時, 分, 秒
print(d)  # 2025-05-01 12:30:45

如果只要日期對象

d = datetime.date(2025, 5, 1)
print(d)  # 2025-05-01

時間加減(使用 timedelta),比如1天后、2小時前、10分鐘后:

timedelta 支持的參數有:days, seconds, microseconds, milliseconds, minutes, hours, weeks

from datetime import datetime, timedeltanow = datetime.now()print(now + timedelta(days=1))      # 一天后
print(now - timedelta(hours=2))     # 兩小時前
print(now + timedelta(minutes=10))  # 十分鐘后

時間格式化輸出(變成字符串)

比如格式化成 "2025-04-29 15:30:42" 這種:

now = datetime.datetime.now()print(now.strftime("%Y-%m-%d %H:%M:%S"))
# 輸出:2025-04-29 15:30:42

字符串轉時間對象(解析時間)

如果拿到的是字符串,比如 "2025-04-29 15:30:42",想轉成 datetime 對象

(注意 strptimestrftime 名字很像,p 是 parse(解析))

s = "2025-04-29 15:30:42"
dt = datetime.datetime.strptime(s, "%Y-%m-%d %H:%M:%S")
print(dt)
# 輸出:2025-04-29 15:30:42

時間比較

可以直接比較兩個 datetime 對象:

t1 = datetime.datetime(2025, 5, 1, 12, 0, 0)
t2 = datetime.datetime(2025, 5, 2, 12, 0, 0)print(t1 < t2)  # True
print(t2 - t1)  # 1 day, 0:00:00 (是一個 timedelta)

循環生成時間段(進階常用)

比如想生成從 2025-04-29 00:00 開始,每隔1小時一個點:

start = datetime.datetime(2025, 4, 29, 0, 0, 0)
end = datetime.datetime(2025, 4, 29, 5, 0, 0)current = start
while current <= end:print(current.strftime("%Y-%m-%d %H:%M:%S"))current += datetime.timedelta(hours=1)

要處理時區,就要用到 tzinfo,不過一般推薦配合第三方庫 pytzzoneinfo 來做。

from datetime import datetime, timezone, timedelta# 設置時區:UTC+8
dt = datetime(2025, 4, 29, 12, 0, 0, tzinfo=timezone(timedelta(hours=8)))
print(dt)

3. re(正則表達式)

正則表達式(Regular Expression)是一種字符串匹配規則的描述語言

它能非常靈活地搜索、提取、替換字符串中的特定內容,比如:

  • 驗證手機號

  • 提取網頁上的郵箱

  • 替換文本中的敏感詞

  • 分割復雜字符串

  • 檢測密碼復雜度

Python 處理正則,靠的就是內置的 re 模塊。

re模塊常用函數

導入:

import re

常用函數有:

函數作用
re.match(pattern, string)字符串開頭匹配
re.search(pattern, string)搜索整個字符串,找到第一個匹配
re.findall(pattern, string)找到所有匹配,返回列表
re.finditer(pattern, string)找到所有匹配,返回迭代器(內存更省)
re.sub(pattern, repl, string)替換匹配到的內容
re.split(pattern, string)按正則分割字符串
re.compile(pattern)編譯成正則對象,提高效率
正則表達式語法基礎
字面意義:

普通字符,自己代表自己,比如 abc 就匹配 abc

元字符(特殊意義的字符):
字符含義
.任意一個字符(除了換行)
^開頭匹配
$結尾匹配
*重復0次或更多次
+重復1次或更多次
?重復0次或1次
{n}恰好n次
{n,}至少n次
{n,m}n到m次
[...]匹配字符集中的任意一個字符
``
()分組(提取、捕獲)
轉義字符(\

如果你想匹配特殊字符,比如? ?.?,必須用? ?\.?

比如:

re.match(r"a\.b", "a.b")  # 匹配成功

注意:正則表達式字符串一般加 r"",表示原生字符串,不轉義。

常用字符集
表達式含義
\d數字,等價于[0-9]
\D非數字
\w字母數字下劃線,等價于[a-zA-Z0-9_]
\W非字母數字下劃線
\s空白字符(空格、tab、換行)
\S非空白字符
貪婪 vs 非貪婪
  • 正則默認是貪婪匹配(能多就多)

  • 在量詞后加 ?,變成非貪婪匹配(能少就少)

例子:

import retext = "<p>Title</p><p>Content</p>"print(re.findall(r"<p>.*</p>", text))    # 貪婪,匹配到整個 "<p>Title</p><p>Content</p>"
print(re.findall(r"<p>.*?</p>", text))   # 非貪婪,分別匹配 "<p>Title</p>" 和 "<p>Content</p>"
典型應用案例

匹配手機號

import rephone = "我的號碼是13812345678,你的呢?"pattern = r"1[3-9]\d{9}"result = re.search(pattern, phone)
print(result.group())  # 輸出:13812345678

提取網頁中的所有郵箱地址

text = "聯系:user1@gmail.com, admin@company.cn, feedback@yahoo.com"emails = re.findall(r"[a-zA-Z0-9._%-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}", text)
print(emails)
# 輸出:['user1@gmail.com', 'admin@company.cn', 'feedback@yahoo.com']

替換敏感詞

text = "這是一段包含badword1和badword2的文字"pattern = r"badword1|badword2"
clean_text = re.sub(pattern, "***", text)
print(clean_text)
# 輸出:這是一段包含***和***的文字

分割復雜字符串

比如有一段文字,逗號、分號、空格都可能作為分隔:

text = "apple,banana;orange  pear"words = re.split(r"[,;\s]+", text)
print(words)
# 輸出:['apple', 'banana', 'orange', 'pear']
分組提取
  • 在正則表達式里,用小括號 () 把一部分內容包起來。

  • 這樣就可以單獨提取出括號里的子匹配

  • 每個括號對應一個組(group),編號從 1 開始。

.group(0)整個匹配到的字符串.group(1), .group(2) 分別是第1個、第2個括號匹配到的內容。

import retext = '姓名:張三,電話:13812345678'pattern = r'姓名:(.*),電話:(1[3-9]\d{9})'result = re.search(pattern, text)print(result.group(0))  # 整個匹配:姓名:張三,電話:13812345678
print(result.group(1))  # 第1組:(.*) -> 張三
print(result.group(2))  # 第2組:(1[3-9]\d{9}) -> 13812345678
compile優化

如果一個正則要重復用多次,可以預編譯成對象:

好處:效率更高,尤其是循環里用的時候。

pattern = re.compile(r"\d+")
print(pattern.findall("123 abc 456"))

總結:re模塊讓你可以用一套靈活的規則(正則表達式),在字符串中快速定位、提取、替換內容,非常強大。


4. json(數據序列化)

JSON(JavaScript Object Notation)是一種輕量級的數據交換格式,特點是:

  • 結構簡單(鍵值對、數組)

  • 可讀性好(人和機器都能輕松理解)

  • 跨語言通用(不只是 JS,Python/Java/Go/后端接口全用)

Python對象和JSON格式互轉,非常適合與前后端接口對接、配置文件讀寫。

樣例 JSON

{"name": "小明","age": 24,"skills": ["Python", "Java", "Hacking"],"has_job": false
}

常用于:

  • 后端接口返回(API)

  • 配置文件(如 .json 結尾)

  • 本地保存數據(緩存)

  • 網絡通信

核心函數用法

Python 提供了內置的 json 模塊,主要做兩件事:

操作函數作用
Python 對象 → JSON 字符串json.dumps()序列化(dump string)
JSON 字符串 → Python 對象json.loads()反序列化(load string)
Python 對象 → 寫入 JSON 文件json.dump()序列化并寫入文件
JSON 文件 → Python 對象json.load()反序列化并讀取文件
json.dumps()

把 Python 對象轉換成 JSON 字符串。

import jsondata = {"name": "小明", "age": 24, "skills": ["Python", "Hacking"]}json_str = json.dumps(data)
print(json_str)
# 輸出:{"name": "\u5c0f\u660e", "age": 24, "skills": ["Python", "Hacking"]}

默認中文會轉成 Unicode 編碼!
想讓中文正常顯示,加參數:

json_str = json.dumps(data, ensure_ascii=False)
print(json_str)
# 輸出:{"name": "小明", "age": 24, "skills": ["Python", "Hacking"]}

美化輸出(縮進):

json_str = json.dumps(data, ensure_ascii=False, indent=2)
print(json_str)

輸出:

{"name": "小明","age": 24,"skills": ["Python","Hacking"]
}
json.loads()

把 JSON 字符串轉換成 Python 對象。

json_str = '{"name": "小明", "age": 24, "skills": ["Python", "Hacking"]}'data = json.loads(json_str)
print(data)
# 輸出:{'name': '小明', 'age': 24, 'skills': ['Python', 'Hacking']}
json.dump()

把 Python 對象寫入到文件中(保存成 .json 文件)。

data = {"name": "小明", "age": 24}with open('data.json', 'w', encoding='utf-8') as f:json.dump(data, f, ensure_ascii=False, indent=2)

寫文件時注意 encoding='utf-8',否則中文可能亂碼。

json.load()

從文件中讀取 JSON 數據,變成 Python 對象。

with open('data.json', 'r', encoding='utf-8') as f:data = json.load(f)
print(data)
Python類型和JSON類型的對應關系
Python類型JSON類型
dict對象(Object)
listtuple數組(Array)
str字符串(String)
intfloat數字(Number)
TrueFalse布爾值(true/false)
None空(null)

注意:Python 的 None 會變成 JSON 的 null

常見應用場景示例

處理 API 接口返回的 JSON

import requests
import jsonresp = requests.get('https://api.example.com/data')
data = json.loads(resp.text)
print(data)

保存爬蟲數據

results = [{"title": "新聞1"}, {"title": "新聞2"}]with open('results.json', 'w', encoding='utf-8') as f:json.dump(results, f, ensure_ascii=False, indent=2)

配置文件讀取

with open('config.json', 'r', encoding='utf-8') as f:config = json.load(f)print(config['api_key'])

總結:json模塊就是把Python數據和JSON字符串互相轉換的橋梁,非常適合用來做接口交互、數據保存、配置管理。


5. collections(高級數據結構)

collections 是 Python 標準庫里的一個模塊。
專門提供比內置數據結構(如 list、dict)更強大、更高效的“容器類”工具。

比如:

  • 更智能的字典(defaultdictOrderedDict

  • 可統計的計數器(Counter

  • 支持隊列操作的雙端隊列(deque

  • 可以給元組加字段名(namedtuple

  • 專業的堆棧/鏈表(ChainMap

常用的有這幾個:

名稱簡單理解作用
namedtuple有名字的元組類似輕量版對象(只有屬性沒有方法)
deque雙端隊列高效插入/刪除元素(兩邊都快)
Counter計數器統計元素出現的次數
OrderedDict有序字典(老版本用)按插入順序記住鍵值對(Python 3.7+內置dict已有序)
defaultdict帶默認值的字典取不存在的key不會報錯,返回默認值
ChainMap多字典組合多個字典邏輯上合并查詢
namedtuple(有名字的元組)

tuple,但可以用名字訪問元素,更直觀。

用法場景:臨時定義小對象,不想寫復雜 class

from collections import namedtuple# 定義一個點
Point = namedtuple('Point', ['x', 'y'])p = Point(1, 2)
print(p.x, p.y)  # 1 2
print(p)         # Point(x=1, y=2)

特點:

  • 占用內存小

  • 代碼簡潔

  • 支持索引訪問,也支持屬性名訪問

deque(雙端隊列)

比 list 更高效,兩邊都能快速添加/刪除元素

用法場景:需要頻繁在頭部/尾部插入或刪除,比如 BFS、滑動窗口。

from collections import dequeq = deque([1, 2, 3])q.append(4)       # 末尾加
q.appendleft(0)   # 開頭加
print(q)          # deque([0, 1, 2, 3, 4])q.pop()           # 刪除末尾
q.popleft()       # 刪除開頭
print(q)          # deque([1, 2, 3])

特性:

  • 頭尾操作都是 O(1) 復雜度

  • 比 list.insert(0, x) 高效得多

Counter(計數器)

用來統計元素出現的次數

用法場景:數據統計、文本詞頻分析。

from collections import Counterc = Counter('abracadabra')
print(c)
# Counter({'a': 5, 'b': 2, 'r': 2, 'c': 1, 'd': 1})print(c.most_common(2))  # 出現最多的2個元素
# [('a', 5), ('b', 2)]

特性:

  • 可以直接加減集合

  • 支持最常見元素提取

OrderedDict(有序字典)

普通 dict 在 Python 3.7+ 默認已經有序,但在老版本(3.6以前)中,OrderedDict很重要。

用法場景:需要維護元素插入順序。

from collections import OrderedDictod = OrderedDict()
od['a'] = 1
od['b'] = 2
od['c'] = 3print(od)  # OrderedDict([('a', 1), ('b', 2), ('c', 3)])

特性:

  • 遍歷時,順序和插入順序一致。

defaultdict(帶默認值的字典)

普通 dict 訪問不存在的 key 會報錯。defaultdict 自動給一個默認值。

用法場景:構建復雜字典(比如分組統計、字典嵌套)

from collections import defaultdictd = defaultdict(int)  # 默認值是 int(), 即0
d['a'] += 1
print(d['a'])  # 1
print(d['b'])  # 0 (不會報錯)# 嵌套使用
tree = defaultdict(lambda: defaultdict(list))
tree['python']['versions'].append(3.9)
print(tree)

特性:

  • 自動初始化新key

  • 很適合做分組/聚合操作

ChainMap(字典鏈)

多個字典組合在一起,查詢時像一個整體。

用法場景:多層配置覆蓋,比如環境變量優先級。

from collections import ChainMapdefaults = {'theme': 'Default', 'language': 'English'}
overrides = {'theme': 'Dark'}settings = ChainMap(overrides, defaults)
print(settings['theme'])    # Dark(優先查overrides)
print(settings['language']) # English(fallback到defaults)

特性:

  • 查詢時,優先從前面的字典查

  • 不是真的合并,只是邏輯組合,非常高效

常見使用場景總結
場景用什么
快速建小對象(無方法的)namedtuple
隊列、棧、滑動窗口deque
統計元素出現次數Counter
需要順序的字典OrderedDict
字典默認值處理defaultdict
多層配置管理ChainMap

6. logging(日志模塊)

logging是 Python 的標準日志模塊,主要功能是:

把程序運行時的關鍵信息輸出到:

  • 控制臺(屏幕)

  • 文件(保存起來)

  • 網絡、郵件、數據庫等(更高級)

讓你:

  • 不再亂用 print

  • 統一管理日志

  • 區分不同重要程度的日志(比如正常信息 vs 錯誤信息)

  • 定制輸出格式、保存位置、保存數量

logging 是專業的 "程序黑匣子",記錄程序的一舉一動,出問題能迅速回溯!

logging內部有四大核心對象

名稱作用
Logger產生日志的對象(你用的入口)
Handler決定日志去哪兒(控制臺?文件?郵箱?)
Formatter決定日志長什么樣(格式)
Filter決定日志過不過濾(可選,不常用)
Logger(負責發日志)↓
Handler(負責把日志發到地方)↓
Formatter(控制日志格式)

每個 Logger 可以有多個 Handler
每個 Handler 都可以指定自己的 Formatter。

比如同時打印到屏幕 + 保存到文件,但格式可以不一樣!

logging常用功能

你常用的基本是這幾種功能:

  • logging.debug() —— 調試信息

  • logging.info() —— 普通運行信息

  • logging.warning() —— 警告(小問題)

  • logging.error() —— 錯誤(程序還能跑)

  • logging.critical() —— 致命錯誤(要崩)

還能做:

  • 設置日志等級(控制打印多少)

  • 保存到日志文件

  • 定時輪換日志(比如每天生成一個新日志)

  • 按大小輪換日志(比如100MB一個文件)

  • 設置日志格式(時間、模塊、行號等信息)

logging的五個等級
等級函數用途默認級別
DEBUGlogging.debug最詳細的調試信息
INFOlogging.info普通的信息,比如程序開始了、結束了
WARNINGlogging.warning警告,程序還能繼續運行?
ERRORlogging.error錯誤,影響功能
CRITICALlogging.critical嚴重錯誤,程序可能崩潰

注意!
默認的日志級別是 WARNING,所以低于 WARNING(比如 DEBUG、INFO)不會顯示,除非你自己改級別!

常見配置方式(兩種)

基本配置

import logginglogging.basicConfig(level=logging.INFO,format="%(asctime)s [%(levelname)s] %(message)s",
)logging.info("程序啟動了")
logging.warning("小心,有點不對勁")
logging.error("程序出錯了!")

輸出示例:

2025-04-29 20:35:00 [INFO] 程序啟動了
2025-04-29 20:35:01 [WARNING] 小心,有點不對勁
2025-04-29 20:35:02 [ERROR] 程序出錯了!

basicConfig 可以快速設置:

  • level:日志等級

  • format:日志格式

  • filename:寫到哪個文件

  • filemode:寫入模式('w'覆蓋,'a'追加)

更復雜的手動配置

import logginglogger = logging.getLogger('my_logger')  # 創建一個Logger
logger.setLevel(logging.DEBUG)           # 設置日志級別# 創建Handler
console_handler = logging.StreamHandler()
file_handler = logging.FileHandler('my_log.log', encoding='utf-8')# 創建Formatter
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')# 綁定Formatter到Handler
console_handler.setFormatter(formatter)
file_handler.setFormatter(formatter)# 綁定Handler到Logger
logger.addHandler(console_handler)
logger.addHandler(file_handler)# 開始使用
logger.info('這是一條info日志')
logger.error('這是一條error日志')

這樣可以:

  • 控制臺有一份

  • 文件保存一份

  • 格式一致

實戰例子
目標寫法示例
設置日志保存到文件filename='xxx.log'
保存中文日志encoding='utf-8'
每天生成一個新日志TimedRotatingFileHandler
文件太大自動切分RotatingFileHandler
改變日志輸出樣式自定義format

日志按大小切割:

from logging.handlers import RotatingFileHandler
import logginghandler = RotatingFileHandler('big.log', maxBytes=1024*1024*5, backupCount=3)
logging.basicConfig(handlers=[handler], level=logging.DEBUG, format='%(asctime)s %(levelname)s %(message)s')logging.info("這是一個測試日志")
  • 單個日志最大5MB

  • 最多保留3個歷史文件(big.log.1, big.log.2, big.log.3)

總結:logging = 專業版print,程序運行過程的黑匣子,調試、追錯、歸檔必備神器!


7. subprocess(執行系統命令)

更安全、更強大、更靈活的執行外部命令方法。

簡單來說:subprocess = 幫你在Python里開一個子進程(子命令行),執行命令,拿到輸出。

流程:

Python程序↓
subprocess模塊↓
操作系統(開子進程,執行系統命令)↓
拿到返回值、輸出結果
subprocess.run() 基礎用法

基本格式:

import subprocesssubprocess.run(["命令", "參數1", "參數2", ...])

例子:

import subprocess# 在Windows上執行 dir
subprocess.run(["dir"], shell=True)# 在Linux上執行 ls -l
subprocess.run(["ls", "-l"])

注意:

  • shell=True:讓命令像直接在終端里那樣執行。

  • 默認 shell=False,更安全。

捕獲輸出(stdout / stderr)

想拿到命令輸出?用 capture_output=True

result = subprocess.run(["ls", "-l"], capture_output=True, text=True)
print(result.stdout)  # 正常輸出
print(result.stderr)  # 錯誤輸出

參數解釋:

  • capture_output=True:自動收集輸出。

  • text=True:讓輸出是字符串(默認是字節bytes)。

傳入參數(列表 vs 字符串)
寫法說明
列表形式推薦!安全!每個參數獨立
字符串形式需要加 shell=True,容易命令注入(危險)

列表寫法(推薦):

subprocess.run(["ping", "www.baidu.com"])

字符串寫法(小心):

subprocess.run("ping www.baidu.com", shell=True)

如果要執行復雜管道命令(比如grep、|管道),必須用 shell=True

更底層的用法(Popen)

如果想實時讀輸出、或者同時操作輸入輸出,用 Popen

簡單例子:

import subprocessp = subprocess.Popen(["ping", "www.baidu.com"], stdout=subprocess.PIPE, text=True)for line in p.stdout:print(line.strip())

這樣可以一行行讀輸出,非常適合:

  • 實時監控命令輸出

  • 做管道(pipe)連接多個命令

常見錯誤和注意事項
錯誤解釋
FileNotFoundError命令打錯了,找不到
PermissionError沒權限執行(尤其是Linux)
UnicodeDecodeError輸出是二進制,不是文本,加 text=True
命令執行失敗查看 result.returncode != 0,說明出錯了

好習慣:

result = subprocess.run(["ls", "-l"], capture_output=True, text=True)if result.returncode != 0:print("命令執行失敗!")print(result.stderr)
else:print(result.stdout)
實戰例子(批量執行 / 調用shell腳本)

批量執行一堆命令:

commands = [["echo", "hello"],["ls", "-l"],["pwd"],
]for cmd in commands:subprocess.run(cmd)

調用本地shell腳本:

比如有一個 test.sh 文件:

#!/bin/bash
echo "Hello from script"

Python執行:

subprocess.run(["bash", "test.sh"])

或者:

subprocess.run("./test.sh", shell=True)

注意腳本要有執行權限(chmod +x test.sh)。

總結
subprocess.run() - 快速執行,拿返回值
subprocess.Popen()- 高級控制,實時操作,讀寫管道
shell=True - 字符串形式(有風險)
capture_output=True- 捕獲輸出
text=True- 輸出是字符串

8. 并發與并行(concurrent.futures、threading、multiprocessing)

概念解釋打比方
并發(Concurrency)同一時間段內處理多個任務(假裝同時做,其實輪著做)一個人炒兩個菜,輪流翻鍋
并行(Parallelism)真正同時處理多個任務(多核心同時進行)兩個人同時炒兩個菜

并發是邏輯上的同時(比如單核CPU上下文切換)
并行是物理上的同時(比如多核CPU各自干活)

Python中的并發并行手段
模塊適用場景特點
threadingI/O密集型任務(網絡、磁盤讀寫)多線程,輕量,但受GIL限制
multiprocessingCPU密集型任務(復雜計算)多進程,真正并行,開銷大
concurrent.futures更高級的線程池/進程池簡單易用,高層封裝

GIL(全局解釋器鎖)讓多線程不能真正并行執行Python代碼,但遇到I/O會釋放鎖。
多進程可以真正利用多核CPU,每個進程都有獨立的Python解釋器。

threading(多線程模塊)

主要用于 I/O密集型任務:比如抓取網頁、文件讀寫、網絡請求。

基本用法

import threadingdef worker():print("我是子線程")# 創建線程
t = threading.Thread(target=worker)# 啟動線程
t.start()# 等待線程結束
t.join()
  • start():啟動線程(真正開始執行)

  • join():主線程等待子線程結束

多線程執行示例

for i in range(5):threading.Thread(target=worker).start()

多線程是共享內存的,可以共享數據,但要小心數據競爭

注意事項

  • GIL導致多線程在Python解釋器層面不是并行的(CPU密集型反而慢)

  • 線程適合用來等待I/O,而不是計算密集的工作

multiprocessing(多進程模塊)

主要用于 CPU密集型任務:比如數據處理、圖像處理、大型計算。

4.1 基本用法

import multiprocessingdef worker():print("我是子進程")if __name__ == '__main__':p = multiprocessing.Process(target=worker)p.start()p.join()
  • start():啟動進程

  • join():等待進程結束

多進程執行示例

if __name__ == '__main__':for i in range(5):multiprocessing.Process(target=worker).start()

每個子進程是完全獨立的,不共享內存

注意事項

  • 多進程開銷大(復制一份整個程序到子進程)

  • 需要用multiprocessing.Queue等方式進行進程間通信

concurrent.futures(高級封裝庫)

Python3之后出的一個超好用模塊,
封裝了線程池 (ThreadPoolExecutor) 和 進程池 (ProcessPoolExecutor)。讓并發變得超級簡單!

基本用法(線程池)

from concurrent.futures import ThreadPoolExecutordef worker(x):return x * xwith ThreadPoolExecutor(max_workers=5) as executor:results = executor.map(worker, [1, 2, 3, 4, 5])for r in results:print(r)
  • max_workers:同時跑幾個線程

  • map:批量提交任務

  • 自動管理 startjoin,不用手動操心!

基本用法(進程池)

from concurrent.futures import ProcessPoolExecutordef worker(x):return x * xwith ProcessPoolExecutor(max_workers=5) as executor:results = executor.map(worker, [1, 2, 3, 4, 5])for r in results:print(r)

一行切換線程池/進程池,爽爆!

三者的區別與選擇
特性threadingmultiprocessingconcurrent.futures
本質線程進程封裝線程池/進程池
適合I/O密集CPU密集兩者皆可
是否并行否(受GIL影響)是(獨立進程)看用的Executor
編程復雜度高(通信麻煩)低(傻瓜式)
內存開銷中等

簡單記憶:

  • 網絡爬蟲文件下載threadingThreadPoolExecutor

  • 復雜計算圖像處理multiprocessingProcessPoolExecutor

  • 不想操心細節concurrent.futures

實戰示例(小項目案例)

用線程池并發抓取網頁

import requests
from concurrent.futures import ThreadPoolExecutorurls = ['http://example.com','http://example.org','http://example.net',
]def fetch(url):r = requests.get(url)print(f"{url}: {r.status_code}")with ThreadPoolExecutor(max_workers=3) as executor:executor.map(fetch, urls)

多線程抓網頁,飛快!

用進程池并行計算

from concurrent.futures import ProcessPoolExecutordef calc(n):total = 0for i in range(10**6):total += i * nreturn totalif __name__ == '__main__':with ProcessPoolExecutor() as executor:results = executor.map(calc, range(5))print(list(results))

多核CPU全開,處理大計算量!

總結

如果做的是:

  • 抓網頁、爬蟲、IO讀寫、等待數據庫 → 用線程threading / ThreadPoolExecutor

  • 大量數據運算、模型訓練、復雜數學計算 → 用進程multiprocessing / ProcessPoolExecutor

  • 不想自己管理啟動關閉,想一行搞定 → concurrent.futures

注意:

  • threading快但是受GIL限制,適合I/O密集

  • multiprocessing真正并行,但開銷更大

  • concurrent.futures非常適合90%的并發場景

IO密集用線程,CPU密集用進程,怕麻煩就用concurrent.futures。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/81635.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/81635.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/81635.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Java基于SaaS模式多租戶ERP系統源碼

目錄 一、系統概述 二、開發環境 三、系統功能介紹 一、系統概述 ERP&#xff0c;全稱 Enterprise Resource Planning 即企業資源計劃。是一種集成化的管理軟件系統&#xff0c;它通過信息技術手段&#xff0c;將企業的各個業務流程和資源管理進行整合&#xff0c;以提高企業…

個人健康中樞的多元化AI網絡革新與精準健康路徑探析

引言 隨著數字化轉型的深入推進,個人健康中樞作為集成化健康管理系統,正在從傳統的單一功能向多元化的AI驅動方向快速發展。在這一背景下,新興網絡硬件技術,特別是DPU(數據處理單元)和全光網絡的出現,為個人健康中樞的革新提供了前所未有的機遇。本研究將深入探討這些技…

AI跑得快,MCP來加速——模型計算平臺在訓練與推理中的硬核作用

AI跑得快,MCP來加速——模型計算平臺在訓練與推理中的硬核作用 一、引言:AI是“鐵人三項”,但訓練+推理常常“掉鏈子” 如今的人工智能系統越來越強,像ChatGPT、Stable Diffusion、Segment Anything等模型不斷刷新技術天花板。但你是否也注意到: 明明模型設計得挺好,訓練…

《MATLAB實戰訓練營:從入門到工業級應用》工程實用篇-自動駕駛初體驗:車道線檢測算法實戰(MATLAB2016b版)

《MATLAB實戰訓練營&#xff1a;從入門到工業級應用》工程實用篇-&#x1f697; 自動駕駛初體驗&#xff1a;車道線檢測算法實戰&#xff08;MATLAB2016b版&#xff09; 大家好&#xff01;今天我要帶大家一起探索自動駕駛中一個非常基礎但又至關重要的技術——車道線檢測。我…

模型部署——cuda編程入門

CUDA中的線程與線程束 kernel是在device上線程中并行執行的函數&#xff0c;核函數用__global__符號聲明&#xff0c;在調用時需要用<<<grid_size, block_size>>>來指定kernel要執行的線程數量。在CUDA中&#xff0c;每一個線程都要執行核函數&#xff0c;并…

WordPress不支持中文TAG標簽出現404的解決方法

我們在后臺編輯文章時輸入中文標簽會發現出現404的情況&#xff0c;其實中文TAG標簽鏈接無法打開的原因是WordPress不支持中文的編碼。那么解決的方法也很容易&#xff0c;只要改代碼讓WordPress能支持中文的編碼形式&#xff0c;也就是UTF-8和GBK編碼即可&#xff0c;無需用到…

金融信貸公司所需的技術和風控體系及其帶來的價值

金融信貸公司的技術架構通過集成傳統大型機系統與現代數據平臺&#xff0c;能夠有效支持金融信貸業務的運作&#xff0c;同時通過大數據、ETL、報表開發、數據倉庫等技術為公司帶來更高效的數據驅動決策、精準的風控分析和更靈活的業務支持。 一、公司技術架構 數據倉庫架構&…

《AI大模型應知應會100篇》第43篇:大模型幻覺問題的識別與緩解方法

第43篇&#xff1a;大模型幻覺問題的識別與緩解方法 摘要 當AI系統自信滿滿地編造"量子計算機使用香蕉皮作為能源"這類荒謬結論時&#xff0c;我們不得不正視大模型的幻覺問題。本文通過15個真實案例解析、6種檢測算法實現和3套工業級解決方案&#xff0c;帶您掌握…

計算方法實驗五 插值多項式的求法

【實驗性質】 綜合性驗 【實驗目的】 掌握Lagrange插值算法、Newton插值算法&#xff1b;理解Newton插值算法相對于Lagrange插值算法的優點。 【實驗內容】 先用C語言自帶的系統函數sin x求出 的值&#xff0c;然后分別用Lagrange、Newton方法求出的值&#xff0c;并與用…

文獻總結:TPAMI端到端自動駕駛綜述——End-to-End Autonomous Driving: Challenges and Frontiers

端到端自動駕駛綜述 1. 文章基本信息2. 背景介紹3. 端到端自動駕駛主要使用方法3. 1 模仿學習3.2 強化學習 4. 測試基準4.1 真實世界評估4.2 在線/閉環仿真測試4.3 離線/開環測試評價 5. 端到端自動駕駛面臨的挑戰5.1 多模態輸入5.2 對視覺表征的依賴5.3 基于模型的強化學習的世…

PostgreSQL:pgAdmin 4 使用教程

pgAdmin 4 是一個用于管理和維護 PostgreSQL 數據庫的強大工具。它提供了一個圖形化界面&#xff0c;使用戶能夠輕松地連接到數據庫、創建表、運行 SQL 語句以及執行其他數據庫管理任務。 安裝和使用 安裝 pgAdmin 4 安裝 pgAdmin 4 非常簡單。下載并運行安裝程序&#xff0…

Java學習手冊:關系型數據庫基礎

一、關系型數據庫概述 關系型數據庫是一種基于關系模型的數據庫&#xff0c;它將數據組織成一個或多個表&#xff08;或稱為關系&#xff09;&#xff0c;每個表由行和列組成。每一列都有一個唯一的名字&#xff0c;稱為屬性&#xff0c;表中的每一行是一個元組&#xff0c;代…

wpf CommandParameter 傳遞MouseWheelEventArgs參數

在 WPF 中通過 CommandParameter 傳遞 MouseWheelEventArgs 參數時&#xff0c;需結合 ?事件到命令的轉換機制? 和 ?參數轉換器? 來實現。以下是具體實現方案及注意事項&#xff1a; 一、核心實現方法 1. ?使用 EventToCommand 傳遞原始事件參數? 通過 Interaction.Tr…

八大排序之選擇排序

本篇文章將帶你詳細了解八大基本排序中的選擇排序 目錄 &#xff08;一&#xff09;選擇排序的時間復雜度和空間復雜度及穩定性分析 &#xff08;二&#xff09;代碼實現 (三)輸出結果 選擇排序的基本原理是&#xff1a;每次從待排序的數組中找出最大值和最小值。具體流程是…

【算法學習】哈希表篇:哈希表的使用場景和使用方法

算法學習&#xff1a; https://blog.csdn.net/2301_80220607/category_12922080.html?spm1001.2014.3001.5482 前言&#xff1a; 在之前學習數據結構時我們就學習了哈希表的使用方法&#xff0c;這里我們主要是針對哈希表的做題方法進行講解&#xff0c;都是leetcode上的經典…

Java 中如何實現自定義類加載器,應用場景是什么?

在 Java 中&#xff0c;可以通過繼承 java.lang.ClassLoader 類來實現自定義類加載器。自定義類加載器可以控制類的加載方式&#xff0c;實現一些特殊的應用場景。 實現自定義類加載器的步驟&#xff1a; 繼承 java.lang.ClassLoader 類。 重寫 findClass(String name) 方法 …

信創開發中跨平臺開發框架的選擇與實踐指南

&#x1f9d1; 博主簡介&#xff1a;CSDN博客專家、CSDN平臺優質創作者&#xff0c;高級開發工程師&#xff0c;數學專業&#xff0c;10年以上C/C, C#, Java等多種編程語言開發經驗&#xff0c;擁有高級工程師證書&#xff1b;擅長C/C、C#等開發語言&#xff0c;熟悉Java常用開…

WebRTC 服務器之Janus架構分析

1. Webrtc三種類型通信架構 1.1 1 對 1 通信 1 對 1 通信模型設計的主要?標是盡量讓兩個終端進?直聯&#xff0c;這樣即可以節省服務器的資源&#xff0c;?可以提? ?視頻的服務質量。WebRTC ?先嘗試兩個終端之間是否可以通過 P2P 直接進?通信&#xff0c;如果?法直接…

數字化轉型進階:26頁華為數字化轉型實踐分享【附全文閱讀】

本文分享了華為數字化轉型的實踐經驗和體會。華為通過數字化變革,致力于在客戶服務、供應鏈、產品管理等方面提高效率,并把數字世界帶入每個組織,構建萬物互聯的智能世界。華為的數字化轉型愿景是成為行業標桿,通過推進數字化戰略、構建面向業務數字化轉型的IT組織陣型、堅…

Hal庫下備份寄存器

首先要確保有外部電源給VBAT供電 生成后應該會有這兩個文件&#xff08;不知道為什么生成了好幾次都沒有&#xff0c;復制工程在試一次就有了&#xff09; 可以看到stm32f407有20個備份寄存器 讀寫函數 void HAL_RTCEx_BKUPWrite(RTC_HandleTypeDef *hrtc, uint32_t Backup…