1.背景

之前一直使用PysimpleGUI来做带图形界面的程序,每次都需要编译成exe发给别人用,一来版本更新就要通知挨个通知更新,二来显示的界面也比较丑,要看大面积的数据,就不方便。

今天午餐时问了一下AI,把我的需求告诉它,它推荐我使用Flask库来实现,详细提出需求,跟它结对编程,大概1个小时,把这个框架和部分代码完成了。

2.成果展示

这是一个日志查看器,可以选择文件,按照时间,设备名称和类型来筛选日志,也可以用正则表达式搜索,并导出搜索结果。实际上它的核心功能是:

grep -E "2024-03-14|A012|"03 03 02" logs.log

通过界面把其中的搜索参数配置好,不需要每次完整的手敲grep 条件。

使用python开发GUI程序-用网页做界面-LMLPHP

3.关键代码

整体由一个python程序和一个html程序构成,都是GPT-4生成的,我做了一些修改。

主要是两点:

1.它不太理解我的搜索条件,以为是下拉框,我改成输入框,然后还有一些引用错误。

2.我希望导入文件后,立即展示在内容显示框,增加了一个联动操作。

from flask import Flask, render_template, request, send_file
import os
import re
import gzip
import json
from datetime import datetime

app = Flask(__name__)

# 日志文件路径
LOG_DIR = 'logs'

# 获取日志文件列表及元数据
def get_log_files():
    files = os.listdir(LOG_DIR)
    log_files = []
    for file in files:
        if file.endswith('.log') or file.endswith('.log.gz'):
            file_path = os.path.join(LOG_DIR, file)
            start_time, end_time, device_types, log_types = parse_log_metadata(file_path)
            log_files.append({
                'name': file,
                'start_time': start_time,
                'end_time': end_time,
                'device_types': device_types,
                'log_types': log_types
            })
    return log_files
#省略80行

def read_log_file(file_path, regex):
    logs = []
    if file_path.endswith('.log.gz'):
        with gzip.open(file_path, 'rt') as f:
            for line in f:
                if regex and not re.search(regex, line):
                    continue
                logs.append(line.strip())
    else:
        with open(file_path, 'r') as f:
            for line in f:
                if regex and not re.search(regex, line):
                    continue
                logs.append(line.strip())
    return logs

if __name__ == '__main__':
    app.run(debug=True)

html文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>日志分析工具</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css">
    <style>
        .log-content {
            height: 500px;
            overflow-y: scroll;
        }
    </style>
</head>
<body>

    <div class="container my-5">
        <h1 class="mb-4">日志分析工具</h1>
        <div class="row mt-3">
            <div class="col-12">
                <div class="input-group">
                    <input type="file" class="form-control" id="file-input" onchange="loadFile()">
                     <button class="btn btn-outline-secondary" type="button" onclick="loadFile()"></button>
                </div>
            </div>
        </div>

#省略200行
        
        <script>
            function loadFile() {
                const fileInput = document.getElementById('file-input');
                const file = fileInput.files[0];
                
                if (!file) {
                    alert('请选择一个文件');
                    return;
                }
                
                const reader = new FileReader();
                reader.onload = function(e) {
                    const logContent = document.getElementById('log-content');
                    logContent.innerHTML = e.target.result.replace(/\n/g, '<br>');
                };
                reader.readAsText(file);
            }

        function searchLogsbyReg() {
            const form = document.getElementById('filter-form');
            const formData = new FormData(form);
            
            fetch('/search', {
                method: 'POST',
                body: formData
            }).then(response => response.json())
                .then(data => {
                    const logContent = document.getElementById('regex');
                    logContent.innerHTML = data.join('<br>');
                });
        }
        function exportLogs() {
            const form = document.getElementById('filter-form');
            const formData = new FormData(form);
            
            fetch('/export', {
                method: 'POST',
                body: formData
            }).then(response => response.blob())
                .then(blob => {
                    const url = URL.createObjectURL(blob);
                    const link = document.createElement('a');
                    link.href = url;
                    link.setAttribute('download', 'logs.txt');
                    document.body.appendChild(link);
                    link.click();
                    document.body.removeChild(link);
                });
        }
    </script>
</body>
</html>

4.网页GUI的好处

1.无需多次编译

        我可以把它放在服务器上,不需要编译成Windows的exe,也可以让windows的同事使用;

2.更新只要一处更新

        每次迭代升级,只要更改这个python文件,再重新运行即可

3.界面更现代化

        比起PysimpleGUI的界面,浏览器看起来更高端大气上档次一点。

使用python开发GUI程序-用网页做界面-LMLPHP使用python开发GUI程序-用网页做界面-LMLPHP

如果需要完整的代码,或与我交流AI辅助编程的事情,欢迎私信我,全网同名。

使用python开发GUI程序-用网页做界面-LMLPHP

 

03-18 21:59