吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 3667|回复: 22
收起左侧

[Python 转载] 首次发帖,新手使用python实现的群ping小工具,求勿喷。。

[复制链接]
uric 发表于 2020-8-1 15:59
本帖最后由 uric 于 2020-8-8 09:48 编辑

====================8.7打包文件================================
说实话python打包确实比较难受,要么体积巨大,要么就是支持不好,我打包过程中发现很奇怪的问题,因多线程主要使用subprocess,pyinstaller支持非常不好,加上-w参数打包成单一文件会发现执行特别缓慢(正常执行3s左右,无窗口单文件执行约30s),但是打包时不加-w参数时正常,比较遗憾,如果是代码层面问题,请大神不吝指导;

成品地址:
https://wwa.lanzouj.com/b0c2mdwzc
密码:52pj


其中:
PingGUI_V3未打包版.zip 此文件使用nuitka进行打包,UI部分编译为C代码,UI响应较快,但因nuitka不支持打包成单一文件,故提供压缩包,解压后点击pingGUIV3.exe执行即可,推荐使用。
PingGUI_CON.exe 此文件为使用pyinstaller进行打包,未添加-w参数,故为单一带console,UI响应较慢,大家自选
====================8.6更新GUI=================================
首先放入demo图片,使用pyqt5,界面使用pyqt5designer设计,使用pyuic转成.py文件:
demo.gif

准备工作:
1、安装pyqt5和pyqt5-tools(建议使用venv环境,避免污染系统python版本)
2、设计UI界面,本次主要选用label实现IP展示,文本框和按钮使用水平布局,IP显示区域使用grid布局,整体上使用垂直布局,可直接使用pyqt5designer加载ping.ui查看或修改,如图:
3、界面代码和业务代码已拆分成2个py文件,其中ping.py为UI文件,pingGUI为业务代码文件,本次重点展示业务代码:
[Python] 纯文本查看 复制代码
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QMessageBox
from PyQt5.QtCore import pyqtSlot, QThread, pyqtSignal
from ping import Ui_pingWindow
import threading
import subprocess
import time
from queue import Queue

# 定义sucess列表、工作进程数和初始化队列
ipSuccess = []
Work_Thread = 254
ipQueue = Queue()

# 初始化主窗口类


class pingWindow(QMainWindow, Ui_pingWindow):
    def __init__(self, parent=None):
        super(pingWindow, self).__init__(parent)
        self.setupUi(self)
        # 初始化多线程对象
        self.thread = Work_QThread()
        # 按钮点击后传给work函数
        self.ping.clicked.connect(self.work)
        # 接收到信号后传递给goStop函数
        self.thread.trigger.connect(self.goStop)
        # 初始化状态栏信息
        self.statusbar.showMessage("请按照提示信息操作...")

    # 执行前清除上一次显示结果
    def clear_color(self):
        # 清除旧颜色,默认颜色为灰色,background-color: rgb(217, 217, 217) 灰色
        for i in range(1, 255):
            ui_default = 'ui.ip_' + \
                str(i) + '.setStyleSheet("background-color: rgb(217, 217, 217)")'
            # 使用eval执行字符串命令/赋值
            eval(ui_default)

    # 点击按钮后的操作
    def work(self):
        a = ui.ip_line.text()
        if len(a) > 0 and len(a.split('.')) == 4 and a.split('.')[-1] == '':
            # 调用清除颜色的函数
            self.clear_color()
            # 多线程调用/执行
            self.thread.start()
            # 任务执行时将ping按钮设置成不可用
            self.ping.setEnabled(False)

        else:
            QMessageBox.information(ui, "提示信息", "检测到输入信息不正确,请输入正确的IP网段信息。")

    # 多线程执行完毕后调用gostop函数
    def goStop(self):
        # 任务结束后恢复按钮可用
        self.ping.setEnabled(True)
        QMessageBox.information(ui, "提示信息", "操作已成功执行。")

    # 多线程ping主函数,注意不需要传入self函数

    def pingIp():
        # 消费队列里的IP地址
        while not ipQueue.empty():
            ip = ipQueue.get()
            # 跟cli一样,linux或macos注意修改为:ping -c 2 -W 5
            cmd = 'ping -n 2 -w 5 %s' % ip
            # 此处未使用管道,直接使用temp临时文件,加快处理速度
            # out_temp = tempfile.TemporaryFile(mode='w+')
            # fileno = out_temp.fileno()
            # p = subprocess.call(cmd, stdout=fileno, stderr=fileno)
            # 判断返回值是0(0代表命令成功执行)
            # if p == 0:
            # 成功返回0,将从队列中遍历的IP信息存入成功列表
            # ipSuccess.append(ip)
            si = subprocess.STARTUPINFO()
            si.dwFlags |= subprocess.STARTF_USESHOWWINDOW
            p = subprocess.Popen(cmd, stdin=subprocess.DEVNULL, stdout=subprocess.PIPE,
                                 stderr=subprocess.STDOUT, universal_newlines=True, startupinfo=si)
            p.communicate()
            # print(p.returncode)
            if p.returncode == 0:
                ipSuccess.append(ip)

# 任务逻辑和主窗口进程拆分,防止出现未响应或程序执行时主界面假死


class Work_QThread(QThread):
    trigger = pyqtSignal()

    def __init__(self):
        super(Work_QThread, self).__init__()

    @pyqtSlot()  # 防止多次执行
    def run(self):

        start_time = time.time()
        ui.statusbar.showMessage("程序执行中...")
        a = ui.ip_line.text()
        for i in range(1, 255):
            ipQueue.put(a + str(i))

        # 获取网段信息并加入队列
        threads = []
        for i in range(Work_Thread):
            # 多线程调用pingIP主函数
            thread = threading.Thread(target=pingWindow.pingIp)
            thread.start()
            threads.append(thread)
        for thread in threads:
            thread.join()

        # 可以ping通的存入sucess列表
        for i in ipSuccess:
            ip_green = 'ip_' + str(i.split(a)[1])
            ui_info = 'ui.' + ip_green + \
                '.setStyleSheet("background-color:green")'  # 修改UI标签背景为绿色
            eval(ui_info)

        time_info = format(time.time() - start_time, '.2f')
        statusbar_info = '在线台数:' + \
            str(len(ipSuccess)) + ' '*5+'执行耗时:' + time_info + 's'

        # 显示状态栏信息
        ui.statusbar.showMessage(statusbar_info)
        # 清除列表,避免重复统计
        ipSuccess.clear()
        # 发送信号
        self.trigger.emit()


if __name__ == '__main__':
    # 初始化PyQt5窗口
    app = QApplication(sys.argv)
    ui = pingWindow()
    ui.show()
    sys.exit(app.exec_())

4、所有文件以附件提供,可使用pyinstaller编译成exe,但实测不加-w参数可正常执行,但是有cmd窗口,加上-w后存在无法执行的情况,这个问题待后续更新解决方案,暂时可不加-w打包,请各位大神不吝指导,非常感谢。
pingGUI V3.zip (13.56 KB, 下载次数: 22)


====================以下为cli版本================================
主要用于是批量ping一个C网段,多线程执行,速度一般在2-5s之内返回结果,激进的话可以调整ping次数为1提示速度,不过容易出现误差;
网络工程师或运维工程师应该会有用,本人萌新首次发帖,此代码杂乱不堪,为python练手之作,求勿喷,如有大神不吝指导,非常感谢!
直接上代码:
[Python] 纯文本查看 复制代码
#!/usr/bin/python3
# coding:utf-8
import sys
import threading
import subprocess
import time
from queue import Queue
from optparse import OptionParser

# 初始化变量,ipSucess为存储可以ping通的IP列表,Work_Thread为后台工作进程数,ipQueue为执行命令的队列
ipSuccess = []
Work_Thread = 254
ipQueue = Queue()


def main(a):
    start_time = time.time()
    # 初始化列表,主要用来存放渲染为绿色的IP信息,"\033[92m \033[0m"
    ip_p = []

    # 默认全部渲染为灰色,同时因为x.x.x.0/24为网络号,无实质意义,替换为空
    for i in range(0, 255):
        t = '\033[90m' + str(i) + '\033[0m'
        ip_p.append(t)
    ip_p[0] = '\033[91m' + '' + '\033[0m'

    # 判断命令行参数-n 或 --net后的字符串是否符合要求,此处判断存在漏洞,需完善
    if len(a) > 0 and len(a.split('.')) == 4 and a.split('.')[-1] == '':
        # 拼接符合要求的数据并放入队列
        for i in range(1, 255):
            ipQueue.put(a + str(i))

        # 初始化线程池,并多线程调用pingIP函数
        threads = []
        for i in range(Work_Thread):
            thread = threading.Thread(target=pingIp)
            thread.start()
            threads.append(thread)
        for thread in threads:
            thread.join()

        # 将可以ping通的IP地址从ipsuccess列表取出并渲染成绿色
        for i in ipSuccess:
            # print(i)
            ip_p[int(i.split('.')[-1])] = '\033[92m' + \
                i.split('.')[-1] + '\033[0m'

        # 该函数定制最终输出内容的格式,每行16个IP,一共16行,其中0和254去除
        def ip_info(ip_p):
            print("Ping Results:")
            n = 16
            for i in range(len(ip_p)):

                print('{0:>12}'.format(ip_p[i]), end=' '*2)
                if (i + 1) % n == 0:
                    print('\n', end='')

        # 将渲染后的结果进行打印
        ip_info(ip_p)

        # 打印提示信息,包括在线主机数和脚本执行时间
        time_info = format(time.time() - start_time, '.2f')
        run_info = a + '在线数:' + \
            str(len(ipSuccess)) + '\t' + '执行耗时:' + time_info + 's'
        print('\n' + run_info)

        # 释放无用资源
        ipSuccess.clear()
        ip_p.clear()
    else:
        # 打印cli提示信息
        parser.print_help()

# 多线程执行命令,并构建ipsuccess列表


def pingIp():
    while not ipQueue.empty():
        ip = ipQueue.get()
        # 如果为linux或macos,此处cmd应为'ping -c 2 -W 5',命令行参数不太一致
        cmd = 'ping -n 2 -w 5 %s' % ip
        # 如果为linux或macos,此处subprocess.call参数需在后面补充shell=True
        res = subprocess.call(cmd, stdout=subprocess.PIPE,
                              stderr=subprocess.PIPE)
        # print(ip, True if res == 0 else False)
        # 如果返回值为0,代表ping命令正确返回,此处仅简单判断状态,后续可读取通道信息,获取延时数据,针对延时时长渲染其他的颜色
        if res == 0:
            ipSuccess.append(ip)


# 从这里开始执行
if __name__ == '__main__':
    # 构建命令行参数
    parser = OptionParser()
    # 本行新增-n或--net参数,参数赋值于变量net
    parser.add_option("-n", "--net",
                      help="for example: ping_cli.py -n 192.168.1.", metavar="net")
    (options, args) = parser.parse_args()
    if options.net != None:
        # 把命令行变量net传给main函数并执行
        main(options.net)
    else:
        # 无法正确获得命令行参数时打印帮助信息并退出程序
        parser.print_help()


执行结果如下:

ping_cli.py

ping_cli.py


PS:因配色方案为bash颜色方案,直接在cmd执行可能无法正常输出颜色标签,经测试Windows Terminal可完美支持颜色渲染(如上图),Linux和MACOS原生支持颜色输出。
后续计划:更改为GUI版,目前已有初稿,待后续完善后更新,参考图如下:


pingGUI.png

免费评分

参与人数 4吾爱币 +7 热心值 +4 收起 理由
windows7 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
taylorSZ22 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
爆炎 + 1 + 1 我很赞同!
苏紫方璇 + 5 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| uric 发表于 2020-8-1 16:11
Menguy 发表于 2020-8-1 16:06
我觉得网址加ping值看着会舒服一点

不同的用途需要重新设计输出内容,我这边工作经常会碰到确认一个网段有多少IP未使用这种需求,ping的延时可以通过subprocess.Popen方法来获取stdout的内容,代码里根据需求处理就可以了。
 楼主| uric 发表于 2020-8-7 10:34
梦想QCJ 发表于 2020-8-7 08:30
这个工具是独立运行吗?

GUI版本打包后可独立运行,不过体积有点大,38M左右,手动滑稽
稍后我上传个打包后的程序吧
 楼主| uric 发表于 2020-8-1 16:04
忘记说了一点,可以直接使用Pyinstaller打包成exe,此处就不上传成品了,有兴趣的童鞋可以试试。
头像被屏蔽
Menguy 发表于 2020-8-1 16:06
提示: 作者被禁止或删除 内容自动屏蔽
绫音 发表于 2020-8-1 16:20
额  学习一下 感谢分享
头像被屏蔽
偶尔平凡 发表于 2020-8-1 16:45
提示: 作者被禁止或删除 内容自动屏蔽
maomaogou 发表于 2020-8-1 16:47
学习一下
战地记者木木子 发表于 2020-8-1 16:48
人生苦短,我用python
wangwanghz 发表于 2020-8-1 16:59
学习学习,谢谢楼主
NOOB玩家 发表于 2020-8-1 17:01
学习了,正在学python
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-26 01:25

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表