在 Eclipse PyDev 中 `from scapy.all import *` 後,編輯器提示 `Undefined variable: IP`,但程式實際執行正常。這是因為 Scapy 使用**動態模組導入機制**(`__getattr__`、`__dir__`、`import hooks`),靜態分析器無法掃描出運行時才注入的符號。本文解釋原理並給出三種解決方案。
from scapy.all import *
# 或
from scapy.all import IP
test_ip = IP(dst="192.168.1.1", src="192.168.1.2") # 運行完全正常
# PyDev 編輯器紅線:Undefined variable: IP
# 明確告訴靜態分析器類別在哪裡
from scapy.layers.inet import IP, TCP, UDP, ICMP
from scapy.layers.l2 import Ether, ARP
from scapy.packet import Raw
from scapy.sendrecv import send, sniff, sr1
# 現在 PyDev 能正確解析 IP、TCP 等
pkt = IP(dst="192.168.1.1")/TCP(dport=80)
send(pkt)
# 官方文件推薦:只導入 all,運行時動態解析
from scapy.all import *
# 代碼提示雖然有紅線,但功能完整
# 若需代碼提示,可配合方案一混用
from scapy.all import * # 運行時用
from scapy.layers.inet import IP # 靜態分析/提示用
import scapy.all as scapy
print('IP' in dir(scapy)) # False (未訪問前)
ip = scapy.IP() # 觸發 __getattr__
print('IP' in dir(scapy)) # True (訪問後注入)
print(scapy.IP is scapy.layers.inet.IP) # True
| 類別 | 所在模組 | 導入建議 |
|---|---|---|
| `IP`, `TCP`, `UDP`, `ICMP` | `scapy.layers.inet` | `from scapy.layers.inet import IP, TCP, UDP, ICMP` |
| `Ether`, `ARP`, `Dot1Q` | `scapy.layers.l2` | `from scapy.layers.l2 import Ether, ARP` |
| `DNS`, `DHCP` | `scapy.layers.dns`, `scapy.layers.dhcp` | 按需導入 |
| `Raw`, `Packet`, `Padding` | `scapy.packet` | `from scapy.packet import Raw` |
| `send`, `sniff`, `sr`, `sr1` | `scapy.sendrecv` | `from scapy.sendrecv import send, sniff` |
**運行正常、編輯器紅線**是 Scapy 動態導入特性決定的。**顯式從子模組導入**可同時滿足運行與靜態分析;或在 PyDev 設定忽略 `scapy.*` 未定義變數檢查。不影響任何功能,放心使用。