Python Ping测试脚本IP去重失效求助:同一IP重复Ping问题
Let's break down why your set-based fix isn't working, and how to actually solve the duplicate ping problem:
The Root Cause
Your current code creates a new empty set (set1 = set()) every single time it finds a line matching your circuit ID. That means each set only ever holds one IP (the one from the current line), so there's no way for it to track which IPs you've already pinged. It's effectively doing the exact same thing as your original list-based code—just using a set instead of a list.
The Fix: Track Pinged IPs Outside the Inner Loop
You need to move the set that tracks pinged IPs to a higher scope, so it persists across all line checks. Here's a revised version of your code that fixes this, plus some other small optimizations:
import glob import os import re os.system("clear") # Precompile the IP regex once (instead of every time we process a line) ip_pattern = re.compile(r'(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})') def getping(ip): response = os.system(f"ping -c 1 {ip}") # Store all circuit IDs in a set for faster lookups with open('circuit_id.txt','r') as f1: cid_set = set(f1.read().splitlines()) # This set will track ALL IPs we've already pinged pinged_ips = set() for filename in glob.glob('testfile[1-2].txt'): with open(filename) as f2: for linef2 in f2: # Check if any circuit ID from our list is in this line line_parts = linef2.split() matched_cid = None for part in line_parts: if part in cid_set: matched_cid = part break if matched_cid: # Extract the IP from the line ip_match = ip_pattern.search(linef2) if ip_match: ip = ip_match[0] # Only ping if we haven't already done so if ip not in pinged_ips: print(f"Circuit ID: {matched_cid}") getping(ip) pinged_ips.add(ip) print("\n=============================================================\n")
Key Improvements Explained
- Persistent Ping Tracking: The
pinged_ipsset lives outside all inner loops, so it keeps track of every IP we've pinged across all files and lines. - Precompiled Regex: We compile the IP regex once at the start, instead of every time we process a matching line—this saves unnecessary computation.
- Faster Circuit ID Checks: We convert the circuit IDs to a set (
cid_set) so checking if a line contains a valid ID is faster (O(1) instead of O(n)). - Error Prevention: We add a check for
ip_matchto avoid crashes if a line has a circuit ID but no valid IP.
Alternative Approach: Collect All Unique IPs First
If you prefer, you can first collect all unique IPs that match any of your circuit IDs, then ping them all at once. This might be easier to read:
import glob import os import re os.system("clear") ip_pattern = re.compile(r'(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})') def getping(ip): response = os.system(f"ping -c 1 {ip}") # Get target circuit IDs with open('circuit_id.txt','r') as f1: cid_set = set(f1.read().splitlines()) # Collect all unique matching IPs unique_ips = set() cid_to_ips = {} # Optional: Track which IPs belong to which circuit ID for filename in glob.glob('testfile[1-2].txt'): with open(filename) as f2: for linef2 in f2: for part in linef2.split(): if part in cid_set: ip_match = ip_pattern.search(linef2) if ip_match: ip = ip_match[0] unique_ips.add(ip) # Optional: Map circuit ID to IP if part not in cid_to_ips: cid_to_ips[part] = set() cid_to_ips[part].add(ip) # Ping each unique IP once for ip in unique_ips: # Optional: Print which circuit IDs this IP belongs to associated_cids = [cid for cid, ips in cid_to_ips.items() if ip in ips] print(f"Pinging IP {ip} (associated with circuit IDs: {', '.join(associated_cids)})") getping(ip) print("\n=============================================================\n")
This approach separates the data collection step from the ping step, which can make debugging easier if you need to verify which IPs you're targeting.
内容的提问来源于stack exchange,提问作者marty

