在 Python 開發中,獲取本機 IP 地址是常見需求。標準庫 socket 提供了豐富的網絡編程接口,能輕鬆實現這一功能。本文整理了幾種主流方案,涵蓋標準庫調用、系統命令輔助以及跨平台兼容性處理,幫助你根據場景選擇最合適的方式。
socket 模塊是 Python 網絡編程的基石。以下是兩個最常用的方法:
socket.gethostbyname(socket.gethostname()) 可根據主機名解析出一個 IPv4 地址。socket.gethostbyname_ex(socket.gethostname()) 返回包含主機名、別名列表、IP 地址列表的元組,適合多網卡環境。若需精確獲取特定網卡(如 eth0、lo)的 IP,可結合 fcntl 和 struct 進行底層系統調用:
import socket
import fcntl
import struct
def get_ip_address(ifname='eth0'):
try:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# SIOCGIFADDR = 0x8915
return socket.inet_ntoa(fcntl.ioctl(
s.fileno(),
0x8915,
struct.pack('256s', ifname[:15].encode())
)[20:24])
except Exception:
# 失敗時回退到解析 ifconfig 輸出
import os
ips = os.popen("LANG=C ifconfig | grep 'inet ' | grep -v '127.0.0.1' | awk '{print $2}'").readlines()
return ips[0].strip() if ips else ''
注意:此方法依賴 Linux 系統調用,Windows 下不可用。代碼中已加入 try-except 降級策略,若 ioctl 失敗則嘗試解析 ifconfig 輸出,增強魯棒性。
Windows 系統常同時存在本地回環地址與外網 IP。可通過遍歷 gethostbyname_ex 返回的列表,過濾掉 127.0.0.1 來獲取真實外網 IP:
import socket
local_ip = socket.gethostbyname(socket.gethostname())
print(f"本地 IP: {local_ip}")
ip_list = socket.gethostbyname_ex(socket.gethostname())[2] # 取地址列表
for ip in ip_list:
if ip != local_ip and not ip.startswith("127."):
print(f"外網 IP: {ip}")
另一種寫法使用 getfqdn 獲取完全合格域名再解析:
myname = socket.getfqdn(socket.gethostname())
myaddr = socket.gethostbyname(myname)
socket.gethostbyname_ex() 無第三方依賴,跨平台性最好。try-except 並提供降級方案。掌握這些方法,無論是編寫網絡診斷腳本、服務註冊發現,還是處理分布式系統中的節點通信,都能遊刃有餘地獲取所需的 IP 地址信息。