在現代軟體開發中,網路介面整合和資料處理扮演著至關重要的角色。本文將會詳細介紹如何使用 Python 與各種網路介面和資料格式進行互動,包含使用 Requests 函式庫簡化 HTTP 請求、操作 RESTful API、解析 JSON 和 XML 資料,以及使用 lxml 進行網頁資料擷取。此外,文章也涵蓋了資料序列化和壓縮技術,例如使用 pickle 進行 Python 物件序列化、XDR 跨語言資料交換,以及 gzip 壓縮技術。最後,我們將探討 Python 標準函式庫中的高效能網路工具,例如 asyncio,並簡要介紹其在分散式系統中的應用。這些技術的整合運用,能有效提升開發效率,並滿足現代網路應用程式對資料處理和通訊的需求。
網路介面與軟體介面整合
本章節將介紹如何使用Python存取目前廣泛用於組織間資料分享的API,並重點介紹多數Python驅動的組織內部基礎設施中用於支援通訊的工具。我們已經在前面的章節中討論了Python對跨行程的管道和佇列的支援,而電腦之間的通訊則需要雙方遵循一套定義好的協定——網際網路遵循的是TCP/IP協定套件。
網路層與應用層協定
TCP/IP協定套件包含四個概念層:鏈結層、網際網路層、傳輸層和應用層。鏈結層負責電腦與網際網路之間的資訊傳輸;網際網路層(例如IPv4、IPv6)控制資料包從源到目的地的傳遞;傳輸層(例如TCP、UDP)定義了兩個端點之間的通訊方式;而應用層(例如FTP、HTTP)則規定了資料的格式以供特定應用程式使用。
Python的標準函式庫提供了實作最常見協定的模組,包括ftplib、poplib、imaplib、nntplib、smtplib、telnetlib和xmlrpc等,用於實作各種應用層協定。
網頁客戶端與HTTP請求
超文字傳輸協定(HTTP)是分散式、協作式超媒體資訊系統的應用層協定,也是全球資訊網資料通訊的基礎。本文重點介紹如何使用Requests函式庫從網頁上取得資料。
Python的標準urllib模組提供了大部分所需的HTTP功能,但使用起來相對底層,需要進行大量工作才能完成看似簡單的任務,例如從需要驗證的HTTPS伺服器取得資料。Requests函式庫簡化了Python中的HTTP請求,使得與網路服務的整合變得無縫。
安裝Requests函式庫
可以使用pip安裝Requests:
$ pip install requests
網路API與RESTful API
現在幾乎每個人,從美國人口普查局到荷蘭國家圖書館,都提供了API供使用者存取他們想要分享的資料;有些API,如Twitter和Facebook,甚至允許使用者(或他們使用的應用程式)修改這些資料。我們可能會聽到「RESTful API」這個術語,REST代表表述性狀態轉移,它是一種指導HTTP 1.1設計的正規化,但不是標準、協定或要求。
使用Requests存取API
以下程式碼展示瞭如何使用Requests存取API:
import requests
result = requests.get('http://pypi.python.org/pypi/requests/json')
這段程式碼實際上對http://pypi.python.org/pypi/requests/json執行了HTTP請求,這是PyPI的JSON後端介面。
HTTP請求方法
在RESTful API中,API設計者選擇伺服器將執行的動作,並在API檔案中告知使用者。常用的HTTP方法包括GET、POST、PUT和DELETE,通常這些「HTTP動詞」會執行其名稱所暗示的操作,例如取得資料、修改資料或刪除資料。
JSON解析
JavaScript物件表示法(JSON)正是JavaScript中用於定義物件的表示法。Requests函式庫在其Response物件中內建了JSON解析器。Python的json模組可以將JSON字串或檔案解析為Python字典(或列表),也可以將Python字典或列表轉換為JSON字串。
JSON範例
以下是一個包含JSON資料的字串:
json_string = '{"first_name": "Guido", "last_name":"van Rossum"}'
可以使用以下程式碼解析它:
import json
parsed_json = json.loads(json_string)
解析後的JSON可以像普通字典一樣使用:
print(parsed_json['first_name'])
"Guido"
程式碼詳解
上述範例中,我們使用了Requests函式庫來傳送HTTP GET請求,並使用json()方法將回應內容解析為JSON格式。這種方式簡化了與網路服務互動的過程,使得開發者能夠更專注於業務邏輯的實作。
程式碼邏輯分析
- 匯入必要的函式庫:首先,我們需要匯入
requests和json函式庫。 - 傳送HTTP請求:使用
requests.get()方法傳送HTTP GET請求到指定的URL。 - 處理回應內容:檢查回應是否成功,並使用
response.json()方法將回應內容解析為JSON格式。 - 存取JSON資料:解析後的JSON資料可以像字典一樣被存取,用於後續的業務邏輯處理。
技術考量
- 使用Requests函式庫可以簡化HTTP請求的處理,避免手動處理查詢字串或POST資料的編碼問題。
- JSON是一種輕量級的資料交換格式,易於閱讀和編寫,同時也易於機器解析和生成。
- 正確處理HTTP請求和回應對於網路應用程式的穩定性和安全性至關重要。
透過上述步驟和技術考量,我們可以有效地使用Python和Requests函式庫來與網路API進行互動,並處理JSON格式的資料。
資料格式轉換與網頁資料擷取
在軟體開發與資料處理的過程中,經常需要處理不同格式的資料,如JSON、XML,以及從網頁中擷取資料等。本文將介紹如何使用Python進行這些操作。
JSON資料處理
JSON(JavaScript Object Notation)是一種輕量級的資料交換格式,廣泛用於網路資料傳輸。Python內建了json模組,可以方便地處理JSON資料。
將Python物件轉換為JSON
可以使用json.dumps()函式將Python物件轉換為JSON格式的字串。例如:
import json
d = {
'first_name': 'Guido',
'last_name': 'van Rossum',
'titles': ['BDFL', 'Developer'],
}
print(json.dumps(d))
#### 內容解密:
此程式碼首先匯入了`json`模組。然後定義了一個字典`d`,包含了Guido van Rossum的基本資訊。使用`json.dumps(d)`將字典轉換為JSON格式的字串,並列印出來。`json.dumps()`函式會將Python物件序列化為JSON格式的字串。
對於較早版本的Python,可以使用simplejson函式庫,它提供了與json模組相同的API,但更新更頻繁。
import simplejson as json
#### 內容解密:
此程式碼匯入了`simplejson`函式庫,並將其別名設為`json`,以便與標準函式庫中的`json`模組保持一致。這樣就可以在較早版本的Python中使用與`json`模組相同的API。
XML資料處理
XML(Extensible Markup Language)是一種標記語言,用於儲存和傳輸資料。Python中有多個函式庫可以處理XML資料,如xml.etree.ElementTree、untangle和xmltodict。
使用untangle處理XML
untangle函式庫可以將XML檔案轉換為Python物件,其結構與XML節點和屬性相符。
import untangle
obj = untangle.parse('path/to/file.xml')
print(obj.root.child['name'])
#### 內容解密:
此程式碼首先匯入了`untangle`函式庫。然後使用`untangle.parse()`函式解析XML檔案,並將結果儲存在`obj`變數中。最後,列印出`child`元素的`name`屬性值。
使用xmltodict處理XML
xmltodict函式庫可以將XML檔案轉換為字典,方便存取元素、屬性和值。
import xmltodict
with open('path/to/file.xml') as fd:
doc = xmltodict.parse(fd.read())
print(doc['mydocument']['@has'])
print(doc['mydocument']['and']['many'])
print(doc['mydocument']['plus']['@a'])
print(doc['mydocument']['plus']['#text'])
#### 內容解密:
此程式碼首先匯入了`xmltodict`函式庫。然後開啟XML檔案,並使用`xmltodict.parse()`函式解析XML內容,將結果儲存在`doc`變數中。最後,列印出XML檔案中各個元素和屬性的值。
網頁資料擷取(Web Scraping)
當網站沒有提供API或CSV、JSON等格式的資料時,可以使用網頁資料擷取技術來取得所需的資料。
使用lxml進行網頁資料擷取
lxml是一個功能強大的函式庫,可以快速解析XML和HTML檔案。
from lxml import html
import requests
page = requests.get('http://econpy.pythonanywhere.com/ex/001.html')
tree = html.fromstring(page.content)
buyers = tree.xpath('//div[@title="buyer-name"]/text()')
prices = tree.xpath('//span[@class="item-price"]/text()')
print(buyers)
print(prices)
#### 內容解密:
此程式碼首先匯入了必要的函式庫。然後使用`requests.get()`函式取得網頁內容,並使用`html.fromstring()`函式解析HTML內容,將結果儲存在`tree`變數中。接著,使用XPath查詢取得買家姓名和價格,並列印出來。
在使用網頁資料擷取技術時,務必遵守網站的服務條款和相關規定,避免對網站造成不必要的負擔。
資料序列化與壓縮技術在Python中的應用
在軟體開發過程中,資料的序列化與壓縮是兩個非常重要的議題。資料序列化是指將結構化的資料轉換成可被儲存或傳輸的格式,並且在接收端能夠還原成原始的資料結構。壓縮技術則是用於減少資料的大小,以節省儲存空間或網路頻寬。
資料序列化
Python提供了多種資料序列化的工具,包括內建的pickle模組,以及支援多種語言的序列化工具如Google的Protobuf和Apache的Avro。
Pickle
pickle是Python的原生序列化模組,可以將Python物件序列化成位元組流,也可以將位元組流還原成Python物件。
import pickle
# 定義一個字典
grades = {'Alice': 89, 'Bob': 72, 'Charles': 87}
# 使用dumps將物件序列化成字串
serial_grades = pickle.dumps(grades)
# 使用loads將字串還原成物件
received_grades = pickle.loads(serial_grades)
print(received_grades)
內容解密:
pickle.dumps()函式用於將Python物件序列化成位元組流。pickle.loads()函式用於將位元組流還原成Python物件。- 需要注意的是,
pickle不支援所有型別的物件,例如函式、方法、類別等。
跨語言序列化
如果需要在不同的程式語言之間交換資料,可以使用支援多種語言的序列化工具,如Google的Protobuf和Apache的Avro。
XDR格式
Python的標準函式庫中包含了xdrlib模組,用於處理Sun的External Data Representation(XDR)格式。XDR是一種與作業系統和傳輸協定無關的資料表示格式。
import socketserver
import xdrlib
class XdrHandler(socketserver.BaseRequestHandler):
def handle(self):
data = self.request.recv(4)
unpacker = xdrlib.Unpacker(data)
message_size = unpacker.unpack_uint()
data = self.request.recv(message_size)
unpacker.reset(data)
print(unpacker.unpack_string())
print(unpacker.unpack_float())
self.request.sendall(b'ok')
server = socketserver.TCPServer(('localhost', 12345), XdrHandler)
server.serve_forever()
內容解密:
xdrlib.Unpacker類別用於將XDR格式的資料還原成Python物件。unpack_uint()、unpack_string()和unpack_float()方法用於還原不同的資料型別。- 需要事先知道資料的結構和順序,才能正確地還原資料。
資料壓縮
Python的標準函式庫中包含了多種資料壓縮和解壓縮的工具,如zlib、gzip、bzip2和lzma。
使用gzip壓縮Pickle資料
import pickle
import gzip
data = "my very big object"
# 將資料壓縮並序列化
with gzip.open('spam.zip', 'wb') as my_zip:
pickle.dump(data, my_zip)
# 將資料解壓縮並還原
with gzip.open('spam.zip', 'rb') as my_zip:
unpickled_data = pickle.load(my_zip)
print(unpickled_data)
內容解密:
gzip.open()函式用於開啟一個gzip檔案。pickle.dump()函式用於將Python物件序列化並寫入檔案。pickle.load()函式用於從檔案中讀取並還原Python物件。
緩衝區協定
Python的緩衝區協定允許開發者減少記憶體中資料的複製次數,從而提高效能。
分散式系統與網路通訊
分散式電腦系統透過相互傳遞資訊共同完成一項任務,例如遊戲對戰、網際網路聊天室或Hadoop計算。本章首先列出我們最受歡迎的網路任務函式庫,接著討論與此類別通訊密切相關的密碼學。
網路通訊
在Python中,連線網路的通訊通常使用非同步工具或執行緒來處理,以繞過全域直譯器鎖(GIL)的單執行緒限制。表9-1中的所有函式庫都解決了同一個問題——繞過GIL——但具有不同的功能和數量。
表9-1 網路通訊函式庫
| 函式庫名稱 | 授權協定 | 使用理由 |
|---|---|---|
| asyncio | PSF授權 | • 提供非同步事件迴圈以管理非阻塞socket和佇列的通訊,以及任何使用者定義的協程。 • 包含非同步socket和佇列。 |
| gevent | MIT授權 | • 與非同步I/O的C函式庫libev緊密耦合。 • 提供根據libev的HTTP伺服器的快速WSGI伺服器。 • 包含gevent.monkey模組,該模組具有標準函式庫的修補功能,因此可以使用gevent使用以阻塞socket編寫的第三方模組。 |
| Twisted | MIT授權 | • 提供較新協定的非同步實作,例如GPS、物聯網(IoCP)和Memcached協定。 • 將其事件迴圈與各種其他事件驅動框架(如wxPython或GTK)整合。 • 內建SSH伺服器和客戶端工具。 |
| PyZMQ | LGPL(ZMQ)和BSD(Python部分)授權 | • 允許使用類別似socket的API設定和介面非阻塞訊息佇列。 • 提供支援分散式計算的socket行為(請求/回應、發布/訂閱和推播/提取)。 • 當您想要建立自己的通訊基礎設施時使用它;它有“Q”在名稱中,但不像RabbitMQ——可以用來建立像RabbitMQ這樣的東西,或是完全不同的行為(取決於所選擇的socket模式)。 |
| pika | BSD授權 | • 提供輕量級的AMQP(通訊協定)客戶端,以連線RabbitMQ或其他訊息代理。 • 包含與Tornado或Twisted事件迴圈一起使用的介面卡。 • 當您想要一個較輕量級的函式庫(沒有網頁儀錶板或其他附加功能),讓您將內容推播到外部訊息代理(如RabbitMQ)時使用它。 |
| Celery | BSD授權 | • 提供AMQP客戶端,以連線RabbitMQ或其他訊息代理。 • 具有將任務狀態儲存在後端中的選項,可以使用不同的流行選項,如透過SQLAlchemy、Memcached等的資料函式庫連線。 • 具有可選的網頁管理和監控工具,稱為Flower。 • 可以與訊息代理(如RabbitMQ)一起使用,以實作開箱即用的訊息代理系統。 |
內容解密:
上述表格中列出的函式庫都用於解決網路通訊中的GIL限制問題,並提供不同的功能和特性。asyncio是Python標準函式庫的一部分,提供非同步事件迴圈和協程支援。gevent和Twisted則是第三方函式庫,分別提供根據libev的快速WSGI伺服器和非同步實作的新協定。PyZMQ、pika和Celery則用於建立和管理訊息佇列和代理。
Python標準函式庫中的效能網路工具
asyncio在Python 3.4中被引入,包含了從開發者社群(如維護Twisted和gevent的社群)中學習到的經驗。它是一種平行工具,常見的應用是網路伺服器。Python自身的asyncore檔案(在Python 3.4中已被棄用)指出:
在單處理器上,有兩種方法可以讓程式同時做多件事情。多執行緒程式設計是最簡單也是最流行的作法,但還有另一種非常不同的技術,可以讓你擁有幾乎所有的多執行緒優點,而不需要實際使用多個執行緒。這種技術只有在程式大多是I/O密集型時才實用。如果程式是CPU密集型的,那麼搶佔式排程的執行緒可能是你真正需要的。然而,網路伺服器很少是CPU密集型的。
asyncio仍然只是Python標準函式庫中的暫定模組——API可能會以向後不相容的方式更改——所以不要太過依賴它。asyncio並非全部都是新的——asyncore(在Python 3.4中已被棄用)具有事件迴圈、非同步socket和非同步檔案I/O,而asynchat(也在Python 3.4中已被棄用)具有非同步佇列。asyncio新增的最大特點是正式化了協程的實作。在Python中,這被正式定義為協程函式——以async def而非def開頭的函式定義。
內容解密:
asyncio是Python 3.4引入的平行工具,主要用於網路伺服器。它解決了單處理器上同時執行多個任務的問題,並提供了事件迴圈、非同步socket和協程等功能。雖然asyncio仍是暫定模組,但它為網路程式設計提供了重要的支援。