Python3写一个exe程序,可以输入IP地址,点击ping按钮,并返回ping的结果

Python开发 阅读(13) 17小时前 发布 扫码查看网页

以下是一个使用Python和Tkinter编写的图形化Ping工具。它会生成一个独立的EXE程序(需配合PyInstaller使用)。

完整代码

python

import subprocess
import sys
import re
import tkinter as tk
from tkinter import scrolledtext, messagebox, ttk
import threading

class PingTool:
    def __init__(self, root):
        self.root = root
        self.root.title("Ping工具 v1.0")
        self.root.geometry("700x500")
        self.root.resizable(True, True)
        
        # 设置样式
        style = ttk.Style()
        style.theme_use('clam')
        
        # 创建主框架
        main_frame = ttk.Frame(root, padding="10")
        main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
        
        # 配置网格权重
        root.columnconfigure(0, weight=1)
        root.rowconfigure(0, weight=1)
        main_frame.columnconfigure(1, weight=1)
        main_frame.rowconfigure(3, weight=1)
        
        # IP地址输入
        ttk.Label(main_frame, text="IP地址或域名:", font=("Arial", 10)).grid(row=0, column=0, sticky=tk.W, pady=5)
        self.ip_entry = ttk.Entry(main_frame, font=("Arial", 10), width=30)
        self.ip_entry.grid(row=0, column=1, sticky=(tk.W, tk.E), pady=5, padx=5)
        self.ip_entry.insert(0, "8.8.8.8")  # 默认示例IP
        
        # Ping次数设置
        ttk.Label(main_frame, text="Ping次数:", font=("Arial", 10)).grid(row=1, column=0, sticky=tk.W, pady=5)
        self.count_var = tk.StringVar(value="4")
        self.count_combo = ttk.Combobox(main_frame, textvariable=self.count_var, values=["1", "2", "3", "4", "5", "10", "20"], width=28, state="readonly")
        self.count_combo.grid(row=1, column=1, sticky=(tk.W, tk.E), pady=5, padx=5)
        
        # 超时设置
        ttk.Label(main_frame, text="超时(秒):", font=("Arial", 10)).grid(row=2, column=0, sticky=tk.W, pady=5)
        self.timeout_var = tk.StringVar(value="2")
        self.timeout_combo = ttk.Combobox(main_frame, textvariable=self.timeout_var, values=["1", "2", "3", "5", "10"], width=28, state="readonly")
        self.timeout_combo.grid(row=2, column=1, sticky=(tk.W, tk.E), pady=5, padx=5)
        
        # 按钮框架
        button_frame = ttk.Frame(main_frame)
        button_frame.grid(row=3, column=0, columnspan=2, pady=10, sticky=tk.W)
        
        self.ping_button = ttk.Button(button_frame, text="开始Ping", command=self.ping_thread, width=12)
        self.ping_button.pack(side=tk.LEFT, padx=5)
        
        self.clear_button = ttk.Button(button_frame, text="清空结果", command=self.clear_output, width=12)
        self.clear_button.pack(side=tk.LEFT, padx=5)
        
        self.stop_button = ttk.Button(button_frame, text="停止", command=self.stop_ping, width=12, state=tk.DISABLED)
        self.stop_button.pack(side=tk.LEFT, padx=5)
        
        # 结果标签
        ttk.Label(main_frame, text="Ping结果:", font=("Arial", 10, "bold")).grid(row=4, column=0, columnspan=2, sticky=tk.W, pady=(10, 5))
        
        # 结果文本框
        self.result_text = scrolledtext.ScrolledText(main_frame, wrap=tk.WORD, width=80, height=20, font=("Consolas", 9))
        self.result_text.grid(row=5, column=0, columnspan=2, sticky=(tk.W, tk.E, tk.N, tk.S), pady=5)
        
        # 状态栏
        self.status_var = tk.StringVar(value="就绪")
        self.status_bar = ttk.Label(root, textvariable=self.status_var, relief=tk.SUNKEN, anchor=tk.W)
        self.status_bar.grid(row=1, column=0, sticky=(tk.W, tk.E))
        
        # 控制变量
        self.ping_process = None
        self.is_pinging = False
        
        # 绑定回车键
        self.ip_entry.bind('<Return>', lambda event: self.ping_thread())
        
    def ping_thread(self):
        """在新线程中执行ping操作,避免界面卡死"""
        if self.is_pinging:
            messagebox.showwarning("警告", "正在执行Ping操作,请稍后...")
            return
        
        target = self.ip_entry.get().strip()
        if not target:
            messagebox.showerror("错误", "请输入IP地址或域名")
            return
        
        # 验证IP格式(简单验证)
        ip_pattern = re.compile(r'^(\d{1,3}\.){3}\d{1,3}$')
        domain_pattern = re.compile(r'^[a-zA-Z0-9][a-zA-Z0-9\.-]+[a-zA-Z0-9]$')
        
        if not ip_pattern.match(target) and not domain_pattern.match(target):
            result = messagebox.askyesno("确认", f"'{target}' 不是有效的IP地址格式,是否继续尝试作为域名解析?")
            if not result:
                return
        
        # 禁用按钮
        self.ping_button.config(state=tk.DISABLED)
        self.stop_button.config(state=tk.NORMAL)
        self.clear_button.config(state=tk.DISABLED)
        self.is_pinging = True
        
        # 启动ping线程
        thread = threading.Thread(target=self.run_ping, args=(target,), daemon=True)
        thread.start()
    
    def run_ping(self, target):
        """执行ping命令"""
        try:
            count = self.count_var.get()
            timeout = self.timeout_var.get()
            
            # 根据操作系统选择ping命令
            if sys.platform == "win32":
                cmd = ["ping", "-n", count, "-w", str(int(timeout) * 1000), target]
            else:  # Linux/Mac
                cmd = ["ping", "-c", count, "-W", timeout, target]
            
            self.update_status(f"正在Ping {target}...")
            self.update_result(f">>> Ping {target} (次数: {count}, 超时: {timeout}秒) <<<\n")
            
            # 执行命令
            self.ping_process = subprocess.Popen(
                cmd,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                text=True,
                encoding='gbk' if sys.platform == "win32" else 'utf-8'
            )
            
            # 读取输出
            for line in self.ping_process.stdout:
                if not self.is_pinging:
                    # 如果被停止,终止进程
                    self.ping_process.terminate()
                    break
                self.update_result(line)
            
            # 读取错误输出
            stderr = self.ping_process.stderr.read()
            if stderr and self.is_pinging:
                self.update_result(f"错误: {stderr}\n")
            
            # 等待进程结束
            if self.ping_process:
                self.ping_process.wait()
            
            if self.is_pinging:
                self.update_result("\n>>> Ping完成 <<<\n")
                self.update_status("就绪")
            else:
                self.update_result("\n>>> Ping已停止 <<<\n")
                self.update_status("已停止")
                
        except Exception as e:
            self.update_result(f"执行出错: {str(e)}\n")
            self.update_status("错误")
        finally:
            # 恢复按钮状态
            self.root.after(0, self.enable_buttons)
    
    def update_result(self, text):
        """更新结果文本框(线程安全)"""
        def _update():
            self.result_text.insert(tk.END, text)
            self.result_text.see(tk.END)  # 自动滚动到底部
        self.root.after(0, _update)
    
    def update_status(self, text):
        """更新状态栏(线程安全)"""
        def _update():
            self.status_var.set(text)
        self.root.after(0, _update)
    
    def enable_buttons(self):
        """恢复按钮状态"""
        self.ping_button.config(state=tk.NORMAL)
        self.stop_button.config(state=tk.DISABLED)
        self.clear_button.config(state=tk.NORMAL)
        self.is_pinging = False
        self.ping_process = None
    
    def stop_ping(self):
        """停止ping操作"""
        if self.is_pinging and self.ping_process:
            try:
                self.ping_process.terminate()
                self.update_result("\n[正在停止...]\n")
                self.update_status("正在停止...")
            except:
                pass
    
    def clear_output(self):
        """清空结果文本框"""
        self.result_text.delete(1.0, tk.END)

def main():
    root = tk.Tk()
    app = PingTool(root)
    root.mainloop()

if __name__ == "__main__":
    main()

打包成EXE文件

方法1:使用PyInstaller(推荐)

  1. 安装PyInstaller
  2. bash
pip install pyinstaller
  1. 打包命令(在代码文件所在目录执行)
  2. bash
pyinstaller --onefile --windowed --name PingTool --icon=ping.ico ping_tool.py

参数说明:

  • --onefile:打包成单个exe文件
  • --windowed:不显示控制台窗口(纯GUI程序)
  • --name:指定exe文件名
  • --icon:指定图标(可选,需要.ico文件)
  • ping_tool.py:你的Python文件名

如果没有图标,可以省略--icon参数:

bash

pyinstaller --onefile --windowed --name PingTool ping_tool.py
  1. 找到生成的EXE打包完成后,在dist文件夹中找到PingTool.exe

方法2:使用auto-py-to-exe(图形化工具)

bash

pip install auto-py-to-exe
auto-py-to-exe

然后在图形界面中:

  1. 选择脚本文件
  2. 选择"One File"
  3. 选择"Window Based"(不显示控制台)
  4. 点击"Convert .py to .exe"

功能特点

  1. 支持IP地址和域名:可以ping IP地址或域名
  2. 可配置参数:Ping次数(1-20次)超时时间(1-10秒)
  3. 停止功能:可以随时停止ping操作
  4. 实时显示结果:边ping边显示结果
  5. 跨平台支持:Windows、Linux、Mac均适用
  6. 多线程设计:ping操作不会卡界面

使用说明

  1. 输入IP地址或域名(默认8.8.8.8)
  2. 选择Ping次数和超时时间
  3. 点击"开始Ping"
  4. 结果会实时显示在下方文本框中
  5. 可以随时点击"停止"中断操作
  6. 点击"清空结果"清除显示内容

注意事项

  • 打包后的exe文件约15-30MB(包含Python运行环境)
  • 在某些安全软件中可能需要添加信任
  • 需要Windows 7及以上版本
  • 确保系统允许运行ping命令

这个工具简单实用,适合网络测试和故障排查。


如遇以下报错:

raise ValueError( ValueError: Received icon image 'D:\2_LearningFiles\Projects\Python\Pythonexe\ping.ico' which exists but is not in the correct form at. On this platform, only ('exe', 'ico') images may be used as icons. If Pillow is installed, automatic conversion will be attempted. Please install Pillow or convert your 'ico' file to one of ('exe', 'ico') and try again.

这个错误是因为PyInstaller在处理ICO文件时遇到了问题。有几种解决方法:

解决方法1:安装Pillow库(最简单)

bash

pip install Pillow

然后重新运行打包命令:

bash

pyinstaller --onefile --windowed --name PingTool ping_tool.py

解决方法2:不使用图标(推荐,最简单)

直接省略图标参数:

bash

pyinstaller --onefile --windowed --name PingTool ping_tool.py

解决方法3:使用正确的ICO文件

如果必须使用图标,确保ICO文件格式正确:

  1. 使用在线工具转换图标访问 https://icoconverter.com/上传你的图片选择尺寸:16x16, 32x32, 48x48, 64x64, 128x128, 256x256下载转换后的ICO文件
  2. 或者使用Python创建ICO文件
  3. python
from PIL import Image

# 创建一个简单的图标(可选)
img = Image.new('RGB', (256, 256), color='blue')
img.save('ping.ico', format='ICO', sizes=[(256, 256)])

解决方法4:使用spec文件

创建一个spec文件来更好地控制打包过程:

  1. 生成spec文件
  2. bash
pyinstaller --onefile --windowed --name PingTool ping_tool.py
  1. 编辑PingTool.spec文件找到 a.datas 部分,确保图标设置正确。
  2. 使用spec文件打包
  3. bash
pyinstaller PingTool.spec

完整的打包命令(无图标版)

bash

# 安装PyInstaller(如果没有)
pip install pyinstaller

# 直接打包(无图标)
pyinstaller --onefile --windowed --name PingTool ping_tool.py

如果需要图标,完整的工作流程:

bash

# 1. 安装Pillow
pip install Pillow

# 2. 确保ICO文件格式正确(使用Pillow验证)
python -c "from PIL import Image; Image.open('ping.ico').save('test.ico', format='ICO')"

# 3. 使用新的ICO文件打包
pyinstaller --onefile --windowed --name PingTool --icon=ping.ico ping_tool.py

快速解决方案(复制即用)

直接复制以下命令,使用无图标版本:

bash

pip install pyinstaller
pyinstaller --onefile --windowed --name PingTool ping_tool.py

打包完成后,在 dist 文件夹中找到 PingTool.exe 即可使用。

验证打包是否成功

  1. 进入dist文件夹
  2. 双击PingTool.exe运行
  3. 输入IP地址(如:8.8.8.8)
  4. 点击"开始Ping"测试功能

推荐使用解决方法2(无图标),因为图标不影响程序功能,且最简单快捷。程序会使用默认的Windows应用程序图标。


#Python

本文标题:Python3写一个exe程序,可以输入IP地址,点击ping按钮,并返回ping的结果
本文链接:https://www.befun.ink/detail/20246.html
声明:本站信息原创或由互联网收集,未用于商业用途,如若侵权,请联系站长删除!