Python网段连通性检测及状态对比代码故障求助
排查并修正你的网段连通性检测与历史状态对比代码
先看看你提供的原代码(有几处明显的逻辑和语法问题):
import os import subprocess import httplib, urllib for ip in range(1,255): ip_addr = "192.168.1." + str(ip) res = subprocess.call(["ping", ip_addr, "-c1", "-W1", "-q"], stdout=open(os.devnull,'w')) if res == 0: print (ip_addr) + " reachable" else: print (ip_addr) + " not reachable" f = open('state_All.txt','r') prestate = f.readline(ip) f.close() prestate = ord(prestate) res = res + 97 if not prestate == res: if prestate == 97: conn = httplib...
代码里的核心问题梳理:
- 字符串拼接语法错误:
print (ip_addr) + " reachable"这种写法会报错,因为print()函数返回None,你不能把None和字符串拼接,应该改成print(f"{ip_addr} reachable")或者print(ip_addr + " reachable")。 - 文件读取逻辑错误:
f.readline(ip)里的参数是读取的字节数,不是读取第ip行。你想要的是读取对应IP的历史状态,应该先把文件里所有行一次性读进来,每行对应一个IP的状态。 - 重复打开文件效率低下:每次循环都打开/关闭文件,不仅慢,还容易出IO问题,应该在循环前就读取所有历史状态,循环后再写入新状态。
- 未处理文件不存在的情况:第一次运行时
state_All.txt不存在,直接用r模式打开会抛出FileNotFoundError,需要先判断文件是否存在,不存在则初始化状态。 - 状态转换的鲁棒性差:用
ord(prestate)转换状态时,如果文件里的内容不是单个字符(比如空行、多余字符),会抛出TypeError,需要做异常处理或者更清晰的状态存储。 - 未完成的HTTP请求逻辑:
conn = httplib...没有写完,需要补全创建连接、发送请求的完整逻辑。
修正后的完整代码
import os import subprocess import httplib import urllib # 定义状态文件路径 STATE_FILE = 'state_All.txt' # 定义网段前缀 SUBNET_PREFIX = '192.168.1.' # 初始化历史状态字典,key是IP,value是状态(0=不可达,1=可达) history_states = {} # 读取历史状态 if os.path.exists(STATE_FILE): with open(STATE_FILE, 'r') as f: # 按行读取,每行格式:192.168.1.x,1(或0) lines = f.readlines() for line in lines: line = line.strip() if not line: continue ip, state = line.split(',') history_states[ip] = int(state) else: # 第一次运行,初始化所有IP为不可达状态 for ip_num in range(1, 255): ip = f"{SUBNET_PREFIX}{ip_num}" history_states[ip] = 0 # 遍历网段检测连通性 current_states = {} for ip_num in range(1, 255): ip_addr = f"{SUBNET_PREFIX}{ip_num}" # 执行ping命令,隐藏输出 res = subprocess.call( ["ping", ip_addr, "-c1", "-W1", "-q"], stdout=open(os.devnull, 'w'), stderr=subprocess.STDOUT ) # 判断连通状态:0=可达,非0=不可达 current_reachable = 1 if res == 0 else 0 current_states[ip_addr] = current_reachable # 打印当前状态 status_text = "reachable" if current_reachable else "not reachable" print(f"{ip_addr} {status_text}") # 对比历史状态 prev_reachable = history_states.get(ip_addr, 0) if current_reachable != prev_reachable: print(f"⚠️ {ip_addr} state changed: {'up' if current_reachable else 'down'}") # 发送HTTP通知(这里以POST请求为例,根据你的需求调整) try: # 替换成你的通知接口地址 conn = httplib.HTTPConnection("your-notify-server.com") params = urllib.urlencode({'ip': ip_addr, 'state': 'up' if current_reachable else 'down'}) headers = {"Content-type": "application/x-www-form-urlencoded", "Accept": "text/plain"} conn.request("POST", "/notify", params, headers) response = conn.getresponse() print(f"Notification sent, response: {response.status} {response.reason}") conn.close() except Exception as e: print(f"Failed to send notification: {str(e)}") # 保存当前状态到文件,覆盖历史状态 with open(STATE_FILE, 'w') as f: for ip, state in current_states.items(): f.write(f"{ip},{state}\n")
修正点说明:
- 状态存储优化:用字典存储历史和当前状态,每个IP对应明确的0/1状态,比字符编码更直观,也避免了
ord()的异常问题。 - 文件操作优化:只在循环前后各读写一次文件,提高效率,同时处理了文件不存在的初始化场景。
- 语法错误修复:修正了print语句的字符串拼接问题,使用f-string更简洁。
- 完善HTTP请求:补全了HTTP POST请求的逻辑,添加了异常捕获,避免通知失败导致程序崩溃。
- 鲁棒性提升:添加了stderr重定向,避免ping命令的错误输出干扰;对空行做了处理,避免读取状态时出错。
内容的提问来源于stack exchange,提问作者bigwin001
相关产品推荐
相关产品推荐

