Python并發與異步編程

Python的并發與異步編程是兩個不同的概念,但它們經常一起使用,以提高程序的性能和響應能力。以下是對這兩個概念的詳細講解:

并發編程 (Concurrency)
并發編程是指在程序中同時執行多個任務的能力。Python提供了幾種實現并發的機制:

1. 多線程 (Threading):
? ?- Python的`threading`模塊允許你創建線程,從而在同一時間內執行多個操作。
? ?- 由于Python的全局解釋器鎖(GIL),真正的并行執行在多線程中受到限制,這意味著在任何給定時間點,只有一個線程可以執行Python字節碼。
? ?- 多線程適合I/O密集型任務,例如網絡請求或文件操作。

2. 多進程 (Multiprocessing):
? ?- `multiprocessing`模塊提供了創建多個進程的方法,每個進程有自己的Python解釋器和內存空間。
? ?- 由于進程之間沒有GIL的限制,因此它們可以實現真正的并行執行。
? ?- 多進程適合CPU密集型任務,但進程間通信和創建進程的開銷較大。

3. 協程 (Coroutines):
? ?- 協程是一種更輕量級的并發機制,通過`asyncio`庫實現。
? ?- 協程允許你編寫看似同步的代碼,而實際上是異步執行的,這使得I/O操作更加高效。

異步編程 (Asynchronous Programming)
異步編程是一種編程范式,允許程序在等待操作完成時繼續執行其他任務。Python中的異步編程主要通過`asyncio`庫實現:

1. asyncio:
? ?- `asyncio`是一個用于編寫單線程并發代碼的庫,使用`async`和`await`關鍵字。
? ?- `async def`用于定義一個異步函數,它可以包含`await`表達式。
? ?- `await`用于等待另一個異步操作完成,同時允許其他異步操作運行。
? ?- `asyncio`提供了事件循環(event loop),它是運行異步任務的核心。2. 使用asyncio的例子:
? ?```python
? ?

import asyncioasync def fetch_data():# 模擬I/O操作await asyncio.sleep(2)return {"data": 1}async def main():# 獲取事件循環引用data = await fetch_data()print(data)asyncio.run(main())


? ?```

3. 異步I/O:
? ?- 除了`asyncio`,Python還提供了用于異步I/O操作的庫,如`aiohttp`用于異步HTTP請求。

并發與異步的結合
在Python中,可以結合使用并發和異步編程來最大化性能。例如,可以使用`asyncio`進行異步編程,同時利用`multiprocessing`來實現CPU密集型任務的并行處理。

注意事項
- 并發編程可能會引入競態條件和死鎖,需要仔細設計。
- 異步編程的代碼可能難以理解和調試,特別是對于初學者。
- 選擇哪種并發或異步模型取決于具體的應用場景和性能要求。

多線程在爬蟲程序中的應用可以顯著提高數據抓取的效率。以下是一個使用Python的`threading`模塊實現的簡單多線程爬蟲案例的詳細講解:

?1. 準備工作
在開始編寫多線程爬蟲之前,需要準備以下內容:
目標網站**:確定要爬取的網站和數據。
請求庫**:如`requests`,用于發送網絡請求。
解析庫**:如`BeautifulSoup`,用于解析HTML頁面。
線程模塊**:`threading`,用于創建和管理線程。

?2. 安裝必要的庫
如果尚未安裝`requests`和`BeautifulSoup`,可以通過以下命令安裝:
```bash

pip install requests beautifulsoup4


```

?3. 編寫爬蟲函數
編寫一個基本的爬蟲函數,用于請求網頁并解析數據。```python

import requests
from bs4 import BeautifulSoupdef crawl(url):try:response = requests.get(url)response.raise_for_status() ?# 檢查請求是否成功soup = BeautifulSoup(response.text, 'html.parser')# 假設我們爬取的是網頁標題title = soup.find('title').get_text()print(f"頁面標題: {title}")except requests.RequestException as e:print(f"請求錯誤: {e}")except Exception as e:print(f"解析錯誤: {e}")


```

?4. 創建線程工作函數
編寫一個線程工作函數,它將作為線程執行的主體。

```python

def worker(url):crawl(url)


```

?5. 管理線程
創建一個函數來管理線程的創建和啟動。```python

def manage_threads(urls):threads = []for url in urls:thread = threading.Thread(target=worker, args=(url,))threads.append(thread)thread.start()# 等待所有線程完成for thread in threads:thread.join()# 爬取的URL列表
urls = ['http://example.com','http://example.org','http://example.net',# 添加更多URL...
]


```

?6. 運行爬蟲
調用`manage_threads`函數并傳入URL列表。

```python

if __name__ == "__main__":manage_threads(urls)


```

?7. 注意事項
GIL限制**:由于Python的GIL,多線程在執行CPU密集型任務時可能不會帶來太大的性能提升。但對于I/O密集型任務,如網絡請求,多線程可以顯著提高效率。
線程安全**:在多線程環境下,共享數據時需要注意線程安全問題,避免競態條件。
資源限制**:過多的線程可能會導致資源競爭和調度問題,需要合理控制線程數量。
異常處理**:每個線程都應該能夠妥善處理異常,避免線程崩潰導致整個程序異常。

?8. 擴展功能
限制速率**:可以引入時間延遲來遵守網站的爬蟲政策。
用戶代理**:設置用戶代理(User-Agent)來模擬瀏覽器請求。
Cookies處理**:處理Cookies以維持會話狀態。
重試機制**:對失敗的請求實施重試策略。

這個案例展示了多線程爬蟲的基本結構和實現方法。在實際應用中,你可能需要根據目標網站的特點和反爬措施進行相應的調整和優化。

讓我們繼續擴展上面的例子,創建一個更完整的多線程爬蟲案例。這個案例將包括以下功能:

1. 多線程爬取網頁
2. 解析網頁內容
3. 限制請求速率
4. 簡單的錯誤處理和日志記錄

首先,我們需要安裝所需的庫(如果尚未安裝):

```bash

pip install requests beautifulsoup4


```

然后,我們將創建一個更完整的多線程爬蟲程序:```python

import requests
from bs4 import BeautifulSoup
import threading
import time
import logging
from queue import Queue# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')# 請求隊列
url_queue = Queue()
# 存放結果的隊列
result_queue = Queue()def crawl(url):try:response = requests.get(url, timeout=5)response.raise_for_status() ?# 檢查請求是否成功soup = BeautifulSoup(response.text, 'html.parser')# 假設我們爬取的是網頁的標題和一些鏈接title = soup.find('title').get_text()links = [a['href'] for a in soup.find_all('a', href=True)]result_queue.put((url, title, links))logging.info(f"成功爬取: {url}")except requests.RequestException as e:logging.error(f"請求錯誤: {url} - {e}")except Exception as e:logging.error(f"解析錯誤: {url} - {e}")def worker():while not url_queue.empty():url = url_queue.get()crawl(url)# 模擬網絡延遲time.sleep(1)def manage_threads(url_list, thread_count=5):# 將URL加入隊列for url in url_list:url_queue.put(url)# 創建并啟動線程threads = []for _ in range(thread_count):thread = threading.Thread(target=worker)threads.append(thread)thread.start()# 等待所有線程完成for thread in threads:thread.join()# 打印結果while not result_queue.empty():url, title, links = result_queue.get()print(f"URL: {url}, Title: {title}, Links: {links}")# 爬取的URL列表
urls = ['http://example.com','http://example.org','http://example.net',# 添加更多URL...
]if __name__ == "__main__":manage_threads(urls, thread_count=10)


```

### 案例詳解:

- 日志記錄:使用`logging`模塊記錄日志,方便跟蹤爬蟲的狀態和錯誤。
- 請求隊列:使用`Queue`來管理URL列表,線程安全地在多個線程間傳遞任務。
- 結果隊列:同樣使用`Queue`來存放爬取的結果。
- 速率限制:通過`time.sleep(1)`模擬網絡延遲,限制請求速率,避免對目標網站造成過大壓力。
- 線程管理:`manage_threads`函數負責初始化隊列、啟動線程和收集結果。

### 注意事項:

- 線程數量:創建的線程數量應根據目標網站和服務器性能進行調整。
- 異常處理:每個線程都應該能夠處理請求和解析過程中可能出現的異常。
- 隊列處理:確保隊列在所有線程中正確地被管理,避免競態條件。
- 資源管理:確保所有網絡請求和線程都正確地被管理,避免資源泄露。

這個案例提供了一個基本的多線程爬蟲框架,可以根據具體需求進行擴展和優化。

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

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

相關文章

嵌入式進階——RTC時鐘

🎬 秋野醬:《個人主頁》 🔥 個人專欄:《Java專欄》《Python專欄》 ??心若有所向往,何懼道阻且長 文章目錄 RTC時鐘原理圖PCF8563寄存器控制與狀態寄存器 設備地址I2C環境初始化RTC寄存器數據讀取RTC寄存器數據寫入RTC鬧鐘設置RTC定時器設置…

2024.5.28晚訓題解

提前預告&#xff0c;市賽初中組會考算法題&#xff0c;應該會有兩道模板題 比如DFS BFS 二分 簡單動態規劃&#xff0c;雖然我們沒學多久&#xff0c;但是模板題你還是要會寫的 A題 編輯距離 動態規劃 注意多組輸入 #include<iostream> using namespace std; int dp[1…

9、C#【進階】特性

特性 文章目錄 1、特性概念2、自定義特性 Attribute3、特性的使用4、限制自定義特性的使用范圍5、系統自帶特性1、過時特性2、調用者信息特性3、條件編譯特性4、外部dll包函數特性 1、特性概念 特性是一種允許我們向程序的程序集添加元數據的語言結構 它是用于保存程序機構信息…

【機器學習300問】103、簡單的經典卷積神經網絡結構設計成什么樣?以LeNet-5為例說明。

一個簡單的經典CNN網絡結構由&#xff1a;輸入層、卷積層、池化層、全連接層和輸出層&#xff0c;這五種神經網絡層結構組成。它最最經典的實例是LeNet-5&#xff0c;它最早被設計用于手寫數字識別任務&#xff0c;包含兩個卷積層、兩個池化層、幾個全連接層&#xff0c;以及最…

ansible批量漏洞升級openssh版本

1、ansible宿主機準備好環境&#xff0c;并寫好hosts文件 [rootoxidized ansible]# cat hosts [all] 10.10.200.33 10.10.200.34 10.10.200.35跑playbook之前記得提前發送秘鑰 ssh-copy-id 10.10.200.33/34/352、下載好安裝包&#xff0c;然后編寫yml [rootoxidized ansible]…

【實用的 IDEA 配置和操作技巧總結】

前置知識 IDEA的設置快捷鍵為ctrlalts鍵&#xff0c;后文介紹IDEA常見的配置就不再贅述這一點了。 基礎配置 取消默認打開上次項目 日常開發都會打開不同的項目&#xff0c;初次安裝IDEA之后&#xff0c;每次打開IDEA都會開啟上一次啟動的項目&#xff0c;所以我們需要進入設…

0基礎學習Mybatis系列數據庫操作框架——Mysql的Geometry數據處理之WKB方案

大綱 序列化反序列化完整TypeHandlerSQL XML完整XML Mapper測試代碼代碼 在《0基礎學習Mybatis系列數據庫操作框架——Mysql的Geometry數據處理之WKT方案》中&#xff0c;我們介紹WTK方案的優點&#xff0c;也感受到它的繁瑣和缺陷。比如&#xff1a; 需要借助ST_GeomFromText…

element+ 引入圖標報錯 Failed to resolve import “@element-plus/icons-vue“ from “

element 引入圖標報錯 Internal server error: Failed to resolve import “element-plus/icons-vue” from “src\components\TimeLine.vue”. Does the file exist? 原因&#xff1a;element-plus需要單獨引入 icons 文檔 pnpm install element-plus/icons-vue之后就可以…

350種類型、10W+量級的API,企業應該怎么管?

忽如一夜春風來&#xff0c;萬物皆可API。 在互聯網時代&#xff0c;API無處不在&#xff1a;企業對外開放的數據、服務和業務能力&#xff0c;以API的形式提供給合作方&#xff1b;企業內部應用與應用、App與App之間的通信&#xff0c;通過API進行&#xff1b;甚至應用內部的…

php 連接sqlserver步驟

1.首先要確定使用的是sqlserver的哪個版本&#xff0c;比如sqlserver2012 2.確定服務器是64位還是32位的 3.確認一下使用php的哪個版本&#xff0c;比如php7.1 SQL Server 的 Microsoft PHP 驅動程序 Microsoft Drivers for PHP 支持矩陣 - PHP drivers for SQL Server | Mi…

Flutter 中的 CupertinoTabView 小部件:全面指南

Flutter 中的 CupertinoTabView 小部件&#xff1a;全面指南 在 Flutter 中&#xff0c;CupertinoTabView 是 Cupertino 組件庫中的一個 widget&#xff0c;它用于創建 iOS 風格的標簽頁視圖。這個 widget 通常與 CupertinoTabScaffold 結合使用&#xff0c;提供了一個底部帶有…

怎么做好客戶信息管理?

根據Forrester的調查表示&#xff0c;客戶滿意度的影響可能會使某些行業的收入每年增加高達 10 億美元。而提升客戶滿意度的關鍵環節便是做好客戶信息管理。但企業在進行客戶信息管理中往往會遇到以下問題&#xff1a; 客戶信息亂&#xff1a;客戶信息存在各個 Excel表格、個人…

PMP報考條件怎么查詢?如何判定自己是否符合條件?

PMP報考條件在PMI官網上就可以查詢&#xff0c;PMP報考條件只需要符合項目管理培訓經歷和項目管理經驗兩個方面的要求即可&#xff0c;大家可以對照下方的規定判斷自己是否符合PMP報名條件 PMP報考條件 以下是PMI&#xff08;中國&#xff09;官網對于PMP報名條件的規定&…

優秀的數據分析師需要具備哪些?

在數據驅動的時代&#xff0c;數據分析師的角色越來越被重視。本文將探討優秀數據分析師必備的三大核心能力&#xff0c;并通過實際案例說明如何將這些能力轉化為業務價值&#xff0c;幫助你在職業道路上更進一步。 在數字化迅速發展的今天&#xff0c;數據分析師扮演著極其重要…

ubuntu strace命令

strace 是 Linux 系統中的一個調試工具&#xff0c;用于跟蹤并記錄系統調用&#xff08;system calls&#xff09;和信號&#xff08;signals&#xff09;。在 Ubuntu 中&#xff0c;strace 命令可以幫助開發者和系統管理員了解一個程序在運行時如何與操作系統內核進行交互&…

TypeScript常見面試題第八節

題目三十六:什么是參數解構? 一、講解視頻 TS面試題三十六:什么是參數解構? 二、題目解析 本題目考察 ts 中的解構,解構是一種特殊語法,可以將對象解構到一個或多個局部變量中,可展開操作符相反,展開是允許將一個數組展開為另一個數組,或將一個對象展開為另一個對象,…

vue+antd實踐:在輸入框光標處插入內容

今天來看一個很簡單的需求。 需求描述&#xff1a;在輸入框光標處&#xff0c;插入指定的內容。 效果如下&#xff1a; 實現思路&#xff1a;剛開始還在想怎么獲取光標的位置&#xff0c;但是發現所做的項目是基于vue3antd組件&#xff0c;那么不簡單了嘛&#xff0c;只要調…

JAVA自制小游戲之推箱子

給家里孩子實現益智游戲開發,教會他怎么使用編程。以下是一個簡單的推箱子游戲的Java實現,包含兩個關卡: 這個程序包含兩個關卡,每個關卡都是一個字符串表示的地圖。游戲會提示玩家輸入移動方向(WASD),然后根據輸入的方向移動玩家。如果玩家成功將所有的箱子推到目標位…

配置物聯網平臺 保姆級教程

一、云平臺配置&#xff08;我們這里使用阿里云&#xff09; 1、注冊和登錄 &#xff08;1&#xff09;找到云平臺官網&#xff0c;點擊右上角的注冊登錄&#xff0c;完成之后&#xff0c;進行實名認證&#xff0c;任選一種認證方式。 ??????? 2、實例的開通和創建 …

Scala環境的搭建

要搭建Scala&#xff0c;我們必須先下載java&#xff0c;由于我的電腦已經搭建好了環境&#xff0c;因此我這里用截圖來教大家搭建環境。 可以從網上搜索安裝包對其進行安裝 IntelliJ IDEA – 領先的 Java 和 Kotlin IDE 不建議下載最新版的&#xff0c;大家下載的版本可以下…