作者: kukey-admin

  • py ppt转图片,横或纵向拼接成一个长图片

    适用于Win系统,依赖于本机安装的Microsoft Office.

    加了界面的代码:

    import os
    import win32com.client as win32
    from PIL import Image
    import tkinter as tk
    from tkinter import filedialog, ttk
    from tkinter import messagebox
    图片路径列表=[]
    def 幻灯片转图片(ppt_path:str, output_folder:str):
        if not os.path.exists(output_folder):
            os.makedirs(output_folder)
        ppt_app = win32.gencache.EnsureDispatch('PowerPoint.Application')
        ppt_app.Visible = True  # 设置为False以在后台运行
    
        ppt = ppt_app.Presentations.Open(ppt_path)
    
        try:
            for i, slide in enumerate(ppt.Slides, start=1):
                slide.Export(os.path.join(output_folder, f'Slide{i}.jpg'), 'JPG')
                图片路径列表.append(output_folder+f'\\Slide{i}.jpg')
        finally:
            ppt.Close()
            ppt_app.Quit()
    
    
    
    def 图片拼接(image_paths:list, output_path:str, direction:str='horizontal'):
        images = [Image.open(x) for x in image_paths]
    
        if direction in ('horizontal','h','横向','横'):
            widths, heights = zip(*(i.size for i in images))
            total_width = sum(widths)
            max_height = max(heights)
            new_img = Image.new('RGB', (total_width, max_height))
            x_offset = 0
            for img in images:
                new_img.paste(img, (x_offset, 0))
                x_offset += img.width
        elif direction in ('vertical','v','纵向','纵'):
            widths = [i.width for i in images]
            if len(set(widths)) > 1:
                raise ValueError("所有图片的宽度必须相同(纵向拼接)")
            heights = [i.height for i in images]
            total_height = sum(heights)
            new_img_width = images[0].width
            new_img = Image.new('RGB', (new_img_width, total_height))
            y_offset = 0
            for img in images:
                new_img.paste(img, (0, y_offset))
                y_offset += img.height
        else:
            raise ValueError("方向必须是 横向或纵向;'horizontal' 或 'vertical'")
        new_img.save(output_path)
    # 选择PPT文件的按钮事件处理函数
    def 选择_ppt_文件():
        ppt_文件路径 = filedialog.askopenfilename(filetypes=[("PowerPoint 文件", "*.pptx")])
        if ppt_文件路径:
            输入框_ppt_文件路径.delete(0, tk.END)
            输入框_ppt_文件路径.insert(0, ppt_文件路径.replace('/','\\'))
    
    # 选择输出文件夹的按钮事件处理函数
    def 选择_输出文件夹():
        输出文件夹 = filedialog.askdirectory()
        if 输出文件夹:
            输入框_输出文件夹.delete(0, tk.END)
            输入框_输出文件夹.insert(0, 输出文件夹.replace('/','\\'))
    def 选择_长图拼接方向():
        拼接方向 = 选择_拼接方向.get()
        print(f"Selected: {拼接方向}")
    # 转换PPT并拼接图片的按钮事件处理函数
    def 转换并拼接():
        ppt_文件路径 = 输入框_ppt_文件路径.get()
        输出文件夹 = 输入框_输出文件夹.get()
        拼接方向 = 选择_拼接方向.get()
        if not ppt_文件路径 or not 输出文件夹:
            messagebox.showerror("错误", "请选择一个PPT文件和一个输出文件夹。")
            return
    
        try:
            幻灯片转图片(ppt_文件路径, 输出文件夹+'\\PPT全部图片')
            print(拼接方向)
            图片拼接(图片路径列表, '111.jpg', 拼接方向)
            messagebox.showinfo("成功", "PPT已成功转换为图片,并且图片已拼接完成。")
        except Exception as e:
            messagebox.showerror("错误", str(e))
    
    def center_window(window):
        # 获取屏幕宽度和高度
        screen_width = window.winfo_screenwidth()
        screen_height = window.winfo_screenheight()
    
        # 获取窗口的宽度和高度
        # 注意:在窗口实际显示之前,这些值可能不准确,因此可能需要调整
        # 这里我们假设已经知道了窗口的大小,或者可以在窗口显示后调用此函数
        window_width = window.winfo_reqwidth()
        window_height = window.winfo_reqheight()
    
        # 计算x和y坐标,使窗口居中
        x = (screen_width // 2) - (window_width // 2)
        y = (screen_height // 2) - (window_height // 2)
    
        # 设置窗口位置
        window.geometry(f'+{x}+{y}')
    
    # 创建Tkinter窗口
    根窗口 = tk.Tk()
    根窗口.title("PPT转图片及图片拼接工具")
    根窗口.geometry("310x240")
    # 调用函数使窗口居中
    center_window(根窗口)
    
    PPT文件_组=tk.Frame(根窗口)
    # 添加标签和输入框
    标签_ppt_文件路径 = tk.Label(PPT文件_组, text="PPT文件路径:")
    标签_ppt_文件路径.pack()
    输入框_ppt_文件路径 = tk.Entry(PPT文件_组)
    输入框_ppt_文件路径.pack(side="left")
    # 添加按钮
    按钮_选择_ppt = tk.Button(PPT文件_组, text="选择PPT", command=选择_ppt_文件)
    按钮_选择_ppt.pack()
    PPT文件_组.pack()
    
    幻灯片转图片的输出文件夹_组=tk.Frame(根窗口)
    标签_输出文件夹 = tk.Label(幻灯片转图片的输出文件夹_组, text="输出文件夹:")
    标签_输出文件夹.pack()
    输入框_输出文件夹 = tk.Entry(幻灯片转图片的输出文件夹_组)
    输入框_输出文件夹.pack(side="left")
    按钮_选择_文件夹 = tk.Button(幻灯片转图片的输出文件夹_组, text="选择文件夹", command=选择_输出文件夹)
    按钮_选择_文件夹.pack()
    幻灯片转图片的输出文件夹_组.pack()
    
    输出图片名_组 = ttk.Frame(根窗口)
    标签_输出图片名 = tk.Label(输出图片名_组, text="输出图片名以及后缀:")
    标签_输出图片名.pack()
    输入框_输出图片名 = tk.Entry(输出图片名_组)
    输入框_输出图片名.pack(side="left")
    输出图片名_组.pack()
    
    拼接方向单选_组 = ttk.Frame(根窗口)
    标签_选择_拼接方向 = tk.Label(拼接方向单选_组, text="拼接方向:")
    标签_选择_拼接方向.pack()
    # 创建一个StringVar对象来跟踪哪个单选按钮被选中
    选择_拼接方向 = tk.StringVar()
    选择_拼接方向.set("横向")  # 设置默认选中的值
    横向=ttk.Radiobutton(拼接方向单选_组, text="横向", variable=选择_拼接方向, value="横向", command=选择_长图拼接方向)
    横向.pack(side="left")
    纵向=ttk.Radiobutton(拼接方向单选_组, text="纵向", variable=选择_拼接方向, value="纵向", command=选择_长图拼接方向)
    纵向.pack(side="left")
    拼接方向单选_组.pack()
    
    # 转换按钮
    按钮_转换并拼接 = tk.Button(根窗口, text="转换PPT并拼接图片", command=转换并拼接)
    按钮_转换并拼接.pack()
    
    # 运行Tkinter事件循环
    根窗口.mainloop()

     

    初始代码:

    import os
    import win32com.client as win32
    from PIL import Image
    图片列表=[]
    def ensure_absolute_path(path:str):
        """
        确保给定的路径是绝对路径。
        如果不是绝对路径,则抛出异常。
    
        参数:
        path (str): 要检查的路径。
    
        抛出:
        ValueError: 如果给定的路径不是绝对路径。
        """
        if not os.path.isabs(path):
            raise ValueError("给定路径不是绝对路径")
    def ppt_to_images(ppt_path:str, output_folder:str):
        """
        根据给定的PPT文件,把每一张幻灯片保存为图片。
    
        :param ppt_path: 图片文件绝对路径
        :param output_folder: 拼接后图片保存的绝对路径
        """
        ensure_absolute_path(ppt_path)
        ensure_absolute_path(output_folder)
        # 确保输出文件夹存在
        if not os.path.exists(output_folder):
            os.makedirs(output_folder)
    
        # 启动PowerPoint应用程序
        ppt_app = win32.gencache.EnsureDispatch('PowerPoint.Application')
        ppt_app.Visible = True  # 设置为False以在后台运行
    
        # 打开PPT文件
        ppt = ppt_app.Presentations.Open(ppt_path)
    
        try:
            # 遍历每个幻灯片
            for i, slide in enumerate(ppt.Slides, start=1):
                # 导出幻灯片为图片
                # 注意:'JPG'是图片格式,'Slide' + 索引 + '.jpg'是文件名
                slide.Export(os.path.join(output_folder, f'Slide{i}.jpg'), 'JPG')
                图片列表.append(output_folder+f'\\Slide{i}.jpg')
        finally:
            # 关闭PPT文件(不保存更改)
            ppt.Close()
            # 退出PowerPoint应用程序
            ppt_app.Quit()
    
    
    
    def concat_images(image_paths:str, output_path:str, direction:str='horizontal'):
        """
        根据给定的方向拼接一组图片。
    
        :param image_paths: 图片文件绝对路径的列表
        :param output_path: 拼接后的图片保存绝对路径
        :param direction: 拼接方向,'horizontal' 或 'vertical'
        """
        images = [Image.open(x) for x in image_paths]
    
        if direction in ('horizontal','h','横向','横'):
            # 横向拼接
            widths, heights = zip(*(i.size for i in images))
            total_width = sum(widths)
            max_height = max(heights)
            new_img = Image.new('RGB', (total_width, max_height))
            x_offset = 0
            for img in images:
                new_img.paste(img, (x_offset, 0))
                x_offset += img.width
        elif direction in ('vertical','v','纵向','纵'):
            # 纵向拼接
            widths = [i.width for i in images]
            if len(set(widths)) > 1:
                raise ValueError("所有图片的宽度必须相同(纵向拼接)")
            heights = [i.height for i in images]
            total_height = sum(heights)
            new_img_width = images[0].width
            new_img = Image.new('RGB', (new_img_width, total_height))
            y_offset = 0
            for img in images:
                new_img.paste(img, (0, y_offset))
                y_offset += img.height
        else:
            raise ValueError("方向必须是 横向或纵向;'horizontal' 或 'vertical'")
    
        # 保存新图片
        new_img.save(output_path)
    
    # 使用示例
    ppt文件绝对路径 = r'C:\Users\rkey\Desktop\测试\植物大战僵尸.pptx'
    导出的路径 = r'C:\Users\rkey\Desktop\测试\导出'
    ppt_to_images(ppt文件绝对路径, 导出的路径)
    # 如果图片名没有路径,则在当前文件夹里创建这个图片,图片名格式自己改
    导出的横向拼接图片名 = '植物大战僵尸.jpg'
    concat_images(图片列表, 导出的横向拼接图片名,'h')
    

     

  • py算命小程序-

    不一定有用,来自吾爱破解https://www.52pojie.cn/thread-1947926-1-1.html

    import tkinter as tk
    from tkinter import ttk
    from datetime import datetime
    from tkinter import messagebox
    import tkinter.filedialog as filedialog
    import random
    import time
    import pickle
    import os
     
    # 将权重字典提取出来作为全局变量
    YEAR_WEIGHTS = {
        "鼠": [1.2, 1.6, 1.5, 0.7, 0.5],
        "牛": [0.9, 0.8, 0.7, 0.7, 0.7],
        "虎": [0.6, 0.8, 0.9, 0.9, 1.2],
        "兔": [0.7, 1.9, 1.2, 1.2, 0.8],
        "龙": [1.2, 1.2, 1.0, 0.8, 0.8],
        "蛇": [0.5, 0.6, 0.7, 0.7, 0.6],
        "马": [0.9, 0.8, 1.5, 1.3, 1.9],
        "羊": [0.8, 0.7, 0.6, 0.5, 0.6],
        "猴": [0.7, 0.5, 0.5, 1.4, 0.8],
        "鸡": [0.8, 1.5, 1.4, 0.5, 1.6],
        "狗": [1.5, 0.6, 1.4, 0.9, 1.0],
        "猪": [0.9, 1.6, 0.9, 1.7, 0.6]
    }
     
    MONTH_WEIGHTS = {
        "正月": 0.6, "二月": 0.7, "三月": 1.8, "四月": 0.9, "五月": 0.5, "六月": 1.6,
        "七月": 0.9, "八月": 1.5, "九月": 1.8, "十月": 0.8, "十一月": 0.9, "十二月": 0.5
    }
     
    DAY_WEIGHTS = {
        "初一": 0.5, "初二": 1.0, "初三": 0.8, "初四": 1.5, "初五": 1.6, "初六": 1.5,
        "初七": 0.8, "初八": 1.6, "初九": 0.8, "初十": 1.6, "十一": 0.9, "十二": 1.7,
        "十三": 0.8, "十四": 1.7, "十五": 1.0, "十六": 0.8, "十七": 0.9, "十八": 1.8,
        "十九": 0.5, "二十": 1.5, "廿一": 1.0, "廿二": 0.9, "廿三": 0.8, "廿四": 0.9,
        "廿五": 1.5, "廿六": 1.8, "廿七": 0.7, "廿八": 0.8, "廿九": 1.6, "三十": 0.6
    }
     
    HOUR_WEIGHTS = {
        "子时(23:00-00:59)": 1.6, "丑时(01:00-02:59)": 0.6, "寅时(03:00-04:59)": 0.7,
        "卯时(05:00-06:59)": 1.0, "辰时(07:00-08:59)": 0.9, "巳时(09:00-10:59)": 1.6,
        "午时(11:00-12:59)": 1.0, "未时(13:00-14:59)": 0.8, "申时(15:00-16:59)": 0.8,
        "酉时(17:00-18:59)": 0.9, "戌时(19:00-20:59)": 0.6, "亥时(21:00-22:59)": 0.6
    }
     
    def load_results(filepath):
        results = {}
        with open(filepath, 'r', encoding='utf-8') as file:  # 尝试使用utf-8编码打开文件
            next(file)  # Skip the header line
            bones_weight, result = None, ''
            for line in file:
                parts = line.strip().split('\t')
                if len(parts) == 2:
                    # 如果当前行可以被分割成两部分,那么它是一个新的记录
                    if bones_weight is not None:
                        # 如果之前已经有一个记录,那么将它添加到结果中
                        results[bones_weight] = result
                    bones_weight, result = parts
                else:
                    # 如果当前行不能被分割成两部分,那么它是上一个记录的一部分
                    result += '\n' + line.strip()
            if bones_weight is not None:
                # 将最后一个记录添加到结果中
                results[bones_weight] = result
        return results
     
    # 定义一个列表来存储十二个属相
    ZODIAC = ["鼠", "牛", "虎", "兔", "龙", "蛇", "马", "羊", "猴", "鸡", "狗", "猪"]
     
    def calculate_weight(year, month, day, hour):
        # 计算出生年份与基准年份的差值
        diff = int(year[:-1]) - 1924
     
        # 计算出生年份在60年循环中的位置
        position = diff % 60
     
        # 计算属相和天干
        zodiac = ZODIAC[position // 5]
        heavenly_stem = position % 10 // 2
     
        # 在字典中查找对应的骨重
        year_weight = YEAR_WEIGHTS[zodiac][heavenly_stem]
        month_weight = MONTH_WEIGHTS.get(month, 0)
        day_weight = DAY_WEIGHTS.get(day, 0)
        hour_weight = HOUR_WEIGHTS.get(hour, 0)
     
        total_weight = year_weight + month_weight + day_weight + hour_weight
        liang = int(total_weight)
        qian = int((total_weight - liang) * 10)
        return f"{liang}两{qian}钱"
     
    def hide_error_message():
        error_label.config(text="")
     
    def load_history():
        if os.path.exists('history.pkl'):
            with open('history.pkl', 'rb') as f:
                return pickle.load(f)
        else:
            return {}
     
    def save_history(history):
        with open('history.pkl', 'wb') as f:
            pickle.dump(history, f)
     
    def show_result(name, age, gender, weight, result):
        # 创建一个新的顶级窗口
        result_window = tk.Toplevel(root)
     
        # 设置窗口标题
        result_window.title("算命结果   *参考唐代玄学家袁天罡称骨算命法* ")
     
        # 创建一个Frame
        frame = tk.Frame(result_window)
        frame.pack(fill="both", expand=True)
     
        # 创建一个Text控件
        text = tk.Text(frame, font=("Microsoft Yahei", 12), wrap="word", padx=18, pady=12)  # 设置边距为18像素
        text.pack(side="left", fill="both", expand=True)
     
        # 创建一个Style对象
        style = ttk.Style()
     
        # 配置滚动条的样式
        style.configure("Vertical.TScrollbar", gripcount=0,
                        background="#C4C4C4", darkcolor="#C4C4C4", lightcolor="#C4C4C4",
                        troughcolor="#C4C4C4", bordercolor="#C4C4C4", arrowcolor="black", width=25 )
     
        # 创建一个滚动条,并应用样式
        scrollbar = ttk.Scrollbar(frame, style="Vertical.TScrollbar")
        scrollbar.pack(side="right", fill="y")
     
        # 将滚动条和Text控件关联起来
        text.config(yscrollcommand=scrollbar.set)
        scrollbar.config(command=text.yview)
     
        # 根据性别选择对应的结果
        if "男命" in result and "女命" in result:
            if gender == "男":
                result = result.split("女命")[0]
            else:
                result = result.split("女命")[1]
     
        # 插入文本
        text.insert("end", f"姓名:{name}\n", "bold")
        text.insert("end", f"年龄:{age}\n", "bold")
        text.insert("end", f"性别:{gender}\n", "bold")
        text.insert("end", f"骨重:{weight}\n\n", "bold")
        text.insert("end", result)
     
        # 设置标签样式
        text.tag_config("bold", foreground="blue", font=("Microsoft Yahei", 13, "bold"))
             
        # 禁止用户编辑文本
        text.config(state="disabled")
     
        # 更新窗口的大小
        result_window.update_idletasks()
     
        # 获取主窗口的位置和大小
        window_info = root.geometry().split('+')
        root_x = int(window_info[1])
        root_y = int(window_info[2])
        root_width = root.winfo_width()
        root_height = root.winfo_height()
     
        # 计算新窗口的位置
        result_window_x = root_x + (root_width - result_window.winfo_width()) // 2
        result_window_y = root_y + (root_height - result_window.winfo_height()) // 2
     
        # 设置新窗口的位置
        result_window.geometry(f"+{result_window_x}+{result_window_y}")
     
        # 创建一个菜单栏
        menubar = tk.Menu(result_window)
        result_window.config(menu=menubar)
     
        def export_result():
            file_path = filedialog.asksaveasfilename(defaultextension="result.txt", filetypes=[("文本文件", "*.txt")])
            if file_path:
                with open(file_path, "w", encoding="utf-8") as f:
                    # 导出更多信息
                    f.write(text.get("1.0", "end"))
                messagebox.showinfo("提示", "导出成功!")
     
        # 创建一个Frame用于放置姓名、年龄等信息和导出按钮
        info_frame = tk.Frame(result_window)
        info_frame.pack(fill="x", padx=18, pady=12)
     
        # 创建导出按钮
        export_button = ttk.Button(info_frame, text="导出结果", command=export_result)
        export_button.pack(side="right")
     
        # 插入姓名、年龄等信息
        info_label = tk.Label(info_frame, text="“本软件算命结果仅供娱乐参考,请勿过于迷信,人生仍需自身努力。”", font=("Microsoft Yahei", 12,"bold"))
        info_label.pack(side="left")
     
        # 设置新窗口的位置
        result_window.geometry(f"+{result_window_x}+{result_window_y}")
     
     
    def get_info(event=None):
        name = entry_name.get()
        year = year_var.get()
        month = month_var.get()
        day = day_var.get()
        hour = hour_var.get()
        gender = gender_var.get()
     
        if not name:
            error_label.config(text="请输入姓名")
            root.after(2000, hide_error_message)
            return
     
        if year == "选择年份" or month == "选择月份" or day == "选择日期" or hour == "选择时辰" or gender == "选择性别":
            error_label.config(text="请完整填写所有信息")
            root.after(2000, hide_error_message)
            return
     
        # 获取当前脚本所在的目录
        script_dir = os.path.dirname(os.path.abspath(__file__))
     
        # 构建 ming.txt 文件的相对路径
        relative_path = "ming.txt"
        file_path = os.path.join(script_dir, relative_path)
     
        # 在结果标签和错误标签之间添加一个进度条
        progress_var = tk.DoubleVar()  # 进度条的值
        progress_bar = ttk.Progressbar(root, variable=progress_var, length=400)
        progress_bar.grid(row=8, column=0, columnspan=2, padx=5, pady=5)
     
        # 显示进度条
        progress_bar.grid()
        result_label.config(text="分析中...", fg="green")
        weight = calculate_weight(year[:-1], month, day, hour)
        results = load_results(file_path)
        result = results.get(weight, "未找到对应的算命结果")
     
        # 模拟一个耗时的操作,更新进度条的值
        progress = 0
        while progress < 100:
            increment = random.randint(1, 24)  # 随机生成进度增量
            progress += increment
            if progress > 100:
                progress = 100
            progress_var.set(progress)  # 更新进度条的值
            root.update_idletasks()  # 强制更新界面
            time.sleep(0.6)  # 暂停0.1秒
     
        # 隐藏进度条
        progress_bar.grid_remove()
     
        # 计算年龄
        birth_year = int(year[:-1])
        current_year = datetime.now().year
        age = current_year - birth_year
     
        show_result(name, age, gender, weight, result)
        result_label.config(text="算命完成!", fg="green")
        root.after(2500, lambda: result_label.config(text=""))  # 2.5秒后清空结果标签
     
        # 保存历史记录
        history = load_history()
        history[name] = (gender, year, month, day, hour)
        save_history(history)
     
    if __name__ == "__main__":
        root = tk.Tk()
        root.title("李氏算命 V1.1")
     
        # 设置窗口的大小和位置
        width = 500  # 窗口的宽度
        height = 440  # 窗口的高度,使得长宽比为5:4
        screen_width = root.winfo_screenwidth()  # 屏幕的宽度
        screen_height = root.winfo_screenheight()  # 屏幕的高度
        x = (screen_width - width) // 2  # 窗口的横坐标,使得窗口在屏幕中居中
        y = (screen_height - height) // 2  # 窗口的纵坐标,使得窗口在屏幕中居中
        root.geometry(f"{width}x{height}+{x}+{y}")  # 设置窗口的大小和位置
     
        # 设置字体大小和样式
        font = ("Microsoft Yahei", 14)
     
        style = ttk.Style()
        style.configure("TCombobox", fieldbackground="white", background="white", arrowcolor="black", selectbackground="#3399fe", selectforeground="white")
     
        def on_name_changed(*args):
            name = name_var.get()
            history = load_history()
            if name in history:
                gender, year, month, day, hour = history[name]
                gender_var.set(gender)
                year_var.set(year)
                month_var.set(month)
                day_var.set(day)
                hour_var.set(hour)
     
        label_name = tk.Label(root, text="姓      名:", font=font)
        label_name.grid(row=0, column=0, padx=5, pady=5, sticky='ew')
     
        name_var = tk.StringVar(root)
        name_var.trace('w', on_name_changed)
        entry_name = ttk.Entry(root, textvariable=name_var, width=20, font=font)
        entry_name.grid(row=0, column=1, padx=5, pady=5, sticky='ew')
     
        # 定义一个字典来存储每个年份对应的闰月
        LEAP_MONTHS = {
            1903: "闰五月", 1906: "闰四月", 1909: "闰二月", 1911: "闰六月", 1914: "闰五月", 1917: "闰二月", 1919: "闰七月",
            1922: "闰五月", 1925: "闰四月", 1928: "闰二月", 1930: "闰六月", 1933: "闰五月", 1936: "闰三月", 1938: "闰七月",
            1941: "闰六月", 1944: "闰四月", 1947: "闰二月", 1949: "闰七月", 1952: "闰五月", 1955: "闰三月", 1957: "闰八月",
            1960: "闰六月", 1963: "闰四月", 1966: "闰三月", 1968: "闰七月", 1971: "闰五月", 1974: "闰四月", 1976: "闰八月",
            1979: "闰六月", 1982: "闰四月", 1984: "闰十月", 1987: "闰六月", 1990: "闰五月", 1993: "闰三月", 1995: "闰八月",
            1998: "闰五月", 2001: "闰四月", 2004: "闰二月", 2006: "闰七月", 2009: "闰五月", 2012: "闰四月", 2014: "闰九月",
            2017: "闰六月", 2020: "闰四月", 2023: "闰二月", 2025: "闰六月", 2028: "闰五月", 2031: "闰三月", 2033: "闰十一月",
            2036: "闰六月", 2039: "闰五月", 2042: "闰二月", 2044: "闰七月", 2047: "闰五月", 2050: "闰三月", 2052: "闰八月",
            2055: "闰六月", 2058: "闰四月", 2061: "闰三月", 2063: "闰七月", 2066: "闰五月", 2069: "闰四月", 2071: "闰八月",
            2074: "闰六月", 2077: "闰四月", 2080: "闰三月", 2082: "闰七月", 2085: "闰五月", 2088: "闰四月", 2090: "闰八月",
            2093: "闰六月", 2096: "闰四月", 2099: "闰二月"
        }
     
        # 定义年份变量
        year_var = tk.StringVar(root)
     
        # 更新月份选项的函数
        def update_month_options(*args):
            year = year_var.get()
            if year.endswith("年"):
                year = int(year[:-1])
                months = ["正月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"]
                if year in LEAP_MONTHS:
                    leap_month = LEAP_MONTHS[year]
                    # 找到闰月对应的月份,并插入闰月
                    for i, month in enumerate(months):
                        if leap_month.endswith(month):
                            months.insert(i + 1, leap_month)
                            break
                month_combobox['values'] = months
     
        # 绑定年份选择事件
        year_var.trace('w', update_month_options)
     
        # 在其他输入框下面添加一个新的输入框
        label_gender = tk.Label(root, text="性      别:", font=font)
        label_gender.grid(row=1, column=0, padx=5, pady=5, sticky='ew')
     
        gender_var = tk.StringVar(root)
        gender_combobox = ttk.Combobox(root, textvariable=gender_var, values=["男", "女"], state="readonly", width=18, font=font)
        gender_combobox.set("选择性别")
        gender_combobox.grid(row=1, column=1, padx=5, pady=5, sticky='ew')
     
        # 更新月份选项
        update_month_options()
     
        label_year = tk.Label(root, text="出生年份:", font=font)
        label_year.grid(row=2, column=0, padx=5, pady=5, sticky='ew')
     
        year_combobox = ttk.Combobox(root, textvariable=year_var, values=[f"{i}年" for i in range(2027, 1939, -1)], state="readonly", width=18, font=font)
        year_combobox.set("选择年份")
        year_combobox.grid(row=2, column=1, padx=5, pady=5, sticky='ew')
     
        label_month = tk.Label(root, text="出生月份:", font=font)
        label_month.grid(row=3, column=0, padx=5, pady=5, sticky='ew')
     
        month_var = tk.StringVar(root)
        month_combobox = ttk.Combobox(root, textvariable=month_var, values=["正月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"], state="readonly", width=18, font=font)
        month_combobox.set("选择月份")
        month_combobox.grid(row=3, column=1, padx=5, pady=5, sticky='ew')
     
        label_day = tk.Label(root, text="出生日期:", font=font)
        label_day.grid(row=4, column=0, padx=5, pady=5, sticky='ew')
     
        month_var = tk.StringVar(root)
        month_combobox = ttk.Combobox(root, textvariable=month_var, values=["正月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"], state="readonly", width=18, font=font)
        month_combobox.set("选择月份")
        month_combobox.grid(row=3, column=1, padx=5, pady=5, sticky='ew')
     
        label_day = tk.Label(root, text="出生日期:", font=font)
        label_day.grid(row=4, column=0, padx=5, pady=5, sticky='ew')
     
        day_var = tk.StringVar(root)
        day_combobox = ttk.Combobox(root, textvariable=day_var, values=["初一", "初二", "初三", "初四", "初五", "初六", "初七", "初八", "初九", "初十", "十一", "十二", "十三", "十四", "十五", "十六", "十七", "十八", "十九", "二十", "廿一", "廿二", "廿三", "廿四", "廿五", "廿六", "廿七", "廿八", "廿九", "三十"], state="readonly", width=18, font=font)
        day_combobox.set("选择日期")
        day_combobox.grid(row=4, column=1, padx=5, pady=5, sticky='ew')
     
        label_hour = tk.Label(root, text="具体时间:", font=font)
        label_hour.grid(row=5, column=0, padx=5, pady=5, sticky='ew')
     
        hour_var = tk.StringVar(root)
        hour_combobox = ttk.Combobox(root, textvariable=hour_var, values=["子时(23:00-00:59)", "丑时(01:00-02:59)", "寅时(03:00-04:59)", "卯时(05:00-06:59)", "辰时(07:00-08:59)", "巳时(09:00-10:59)", "午时(11:00-12:59)", "未时(13:00-14:59)", "申时(15:00-16:59)", "酉时(17:00-18:59)", "戌时(19:00-20:59)", "亥时(21:00-22:59)"], state="readonly", width=18, font=font)
        hour_combobox.set("选择时辰")
        hour_combobox.grid(row=5, column=1, padx=5, pady=5, sticky='ew')
     
        # 创建一个Frame作为按钮的容器,设置背景颜色为蓝色
        button_frame = tk.Frame(root, bg="black")
        button_frame.grid(row=6, column=0, columnspan=2, padx=5, pady=5, sticky='ew')
     
        # 创建一个按钮,设置背景颜色为白色,放入Frame中
        button_submit = tk.Button(button_frame, text="开始算命", command=get_info, font=("Microsoft Yahei", 14), bg="white", width=140)
        button_submit.pack(padx=1.5, pady=1.5)  # 设置边框宽度为2像素
     
        notice_label = tk.Label(root, text="*注意:出生日期为农历", fg="red", font=font)
        notice_label.grid(row=7, column=0, columnspan=2, padx=5, pady=5, sticky='ew')
     
        root.bind('<Return>', get_info)
     
        # 将结果标签放置在第8行
        result_label = tk.Label(root, text="", wraplength=400, font=font)
        result_label.grid(row=8, column=0, columnspan=2, padx=5, pady=5, sticky='ew')
     
        # 将错误标签放置在第9行
        error_label = tk.Label(root, text="", fg="red", font=font)
        error_label.grid(row=9, column=0, columnspan=2, padx=5, pady=5, sticky='ew')
     
        # 使用sticky选项将标签框架填充满整个单元格
        root.grid_rowconfigure(8, weight=1)
        root.grid_rowconfigure(9, weight=1)  # 添加这一行以确保错误标签也可以填充满单元格
        root.grid_columnconfigure(0, weight=1)
        root.grid_columnconfigure(1, weight=1)
     
        def show_version_info():
            # 创建一个新的顶级窗口
            version_window = tk.Toplevel(root)
     
            # 设置窗口标题
            version_window.title("更多信息")
     
            # 设置窗口的大小
            version_window.geometry("380x320")
     
            # 创建一个Notebook控件
            notebook = ttk.Notebook(version_window)
            notebook.pack(fill="both", expand=True)
     
            # 创建几个Frame控件作为选项卡的内容
            frame1 = tk.Frame(notebook)
            frame2 = tk.Frame(notebook)
            frame3 = tk.Frame(notebook)
            frame4 = tk.Frame(notebook)
            frame5 = tk.Frame(notebook)
     
            # 将Frame控件添加到Notebook控件中
            notebook.add(frame1, text="算命说明")
            notebook.add(frame2, text="称骨算命")
            notebook.add(frame3, text="运行需求")
            notebook.add(frame4, text="了解帮助")
            notebook.add(frame5, text="反馈提交")
     
            # 在每个Frame控件中添加一些内容,并设置anchor和side选项
            tk.Label(frame1, text="称骨算命是一种传统文化中的算命方式,其科学性存疑。使用该程序进行算命仅供娱乐参考,请勿过于迷信。", font=("KaiTi", 13), wraplength=350).pack(ipadx=100,ipady=60)
            tk.Label(frame2, text="称骨算命是由袁天罡创立,根据每个人的生辰八字,年、月、日、时分别的重量计算总合。得出八字重量:称骨重量。然后根据袁天罡称骨算法进行称骨算命。\n 1两=10钱,每一个重量都有详细分析算命结果。", font=("KaiTi", 13), wraplength=350).pack(ipadx=100,ipady=60)
            tk.Label(frame3, text="建议使用 Windows 10 及以上版本系统", font=("KaiTi", 13, "bold"), wraplength=350).pack(ipadx=100,ipady=60)
            tk.Label(frame5, text="如果您有任何问题或建议,欢迎在本帖子下回复或评分。\nhttps://www.52pojie.cn/", font=("KaiTi", 13), wraplength=350).pack(ipadx=10,ipady=10)
     
            # 更新窗口的大小
            version_window.update_idletasks()
     
            # 获取主窗口的位置和大小
            window_info = root.geometry().split('+')
            root_x = int(window_info[1])
            root_y = int(window_info[2])
            root_width = root.winfo_width()
            root_height = root.winfo_height()
     
            # 计算新窗口的位置
            version_window_x = root_x + (root_width - version_window.winfo_width()) // 2
            version_window_y = root_y + (root_height - version_window.winfo_height()) // 2
     
            # 设置新窗口的位置
            version_window.geometry(f"+{version_window_x}+{version_window_y}")
     
            import webbrowser
     
            def open_link_baidu(event):
                webbrowser.open_new(r"https://www.52pojie.cn/")
     
            def open_link_ref(event):
                webbrowser.open_new(r"https://www.52pojie.cn/home.php?mod=follow&uid=2260954")
     
            # 在frame4中添加一些内容
            tk.Label(frame4, text="如果想了解后续更新信息,请点击查看:  吾爱破解:", wraplength=245).pack(ipadx=10,ipady=10)
     
            # 创建一个Text控件
            text_widget_baidu = tk.Text(frame4, height=1, wrap="none")  # height=1表示只显示一行文本
            text_widget_baidu.insert("1.0", "https://www.52pojie.cn/")
            text_widget_baidu.tag_add("link", "1.0", "end")
            text_widget_baidu.tag_config("link", foreground="blue", underline=True)
            text_widget_baidu.tag_bind("link", "<Button-1>", open_link_baidu)
            text_widget_baidu.configure(state="disabled")  # 设置为只读模式
            text_widget_baidu.pack(ipadx=10, ipady=10)
     
            tk.Label(frame4, text="个人主页:").pack(ipadx=10,ipady=10)
     
            # 创建一个Text控件
            text_widget_ref = tk.Text(frame4, height=1, wrap="none")  # height=1表示只显示一行文本
            text_widget_ref.insert("1.0", "https://www.52pojie.cn/home.php?mod=follow&uid=2260954")
            text_widget_ref.tag_add("link", "1.0", "end")
            text_widget_ref.tag_config("link", foreground="blue", underline=True)
            text_widget_ref.tag_bind("link", "<Button-1>", open_link_ref)
            text_widget_ref.configure(state="disabled")  # 设置为只读模式
            text_widget_ref.pack(ipadx=10, ipady=10)
     
        # 显示关于信息的函数
        def show_version1_info():
            version_text = (
                "李氏算命 V1.1\n\n"
                "原创作者: LjhaiDj\n"
                "最近更新:2024年8月1日\n\n"
                "Copyright &#169; 2024 LjhaiDj(吾爱破解). All rights reserved. "
            )
            messagebox.showinfo("关于李氏算命", version_text)
     
        # 显示软件声明信息的函数
        def show_declaration():
            declaration_text = (
                "软件声明:\n"
                "信息参考网上资源以及AI生成,请注意分辨。\n"
                "特别注意: 称骨算命是一种传统文化中的算命方式,其科学性存疑。使用该程序进行算命仅供娱乐参考,请勿过于迷信。\n"
                "如果您有任何问题,请联系开发者。"
            )
            messagebox.showinfo("声明", declaration_text)
     
        # 显示隐私声明信息的函数
        def show_declaration_pra():
            declaration_text = (
                "隐私声明:\n"
                "本软件不会收集您的任何个人信息,请放心输入。\n"
                "本软件不会要求获取设备隐私权限。\n"
                "本程序算命结果仅供参考!"
            )
            messagebox.showinfo("声明", declaration_text)
     
        # 显示权限声明信息的函数
        def show_declaration_power():
            declaration_text = (
                "权限声明:\n"
                "本程序着重在于学习,不要使用本程序做违法乱纪坑蒙拐骗的行为!\n"
                "禁止商用,违者必究!\n"
                "如果转载,请注明出处!谢谢!"
            )
            messagebox.showinfo("声明", declaration_text)
     
        # 显示更新内容的函数
        def show_update_info():
            declaration_text = (
                "最近更新:2024年8月1日\n"
                "软件版本: 李氏算命 V1.1\n"
                "更新内容:\n"
                "1. 更新算法,修复无算命结果错误\n"
                "2. 增加性别选项,结果更清晰\n"
                "3. 补充闰月选项,丰富算命结果\n"
                "4. 添加导出功能,导出算命结果\n"
            "—————————————————————————————\n"
            "后续更新考虑使用新的架构、现代UI和新的算法,并加入更多更专业的内容(八字五行摆盘、星座、婚配、运势等)\n"
            "请大家持续关注,谢谢。"
            )
            messagebox.showinfo("更新内容", declaration_text)
     
        # 创建一个菜单栏
        menu_bar = tk.Menu(root)
        root.config(menu=menu_bar)
     
        # 创建“更新信息”菜单
        help_menu = tk.Menu(menu_bar, tearoff=0)
        menu_bar.add_cascade(label="更新信息", menu=help_menu)
        help_menu.add_command(label="软件版本", command=show_version1_info)
        help_menu.add_command(label="更新内容", command=show_update_info)
     
        # 创建“声明”菜单
        help_menu = tk.Menu(menu_bar, tearoff=0)
        menu_bar.add_cascade(label="声明", menu=help_menu)
        help_menu.add_command(label="软件声明", command=show_declaration)
        help_menu.add_command(label="隐私声明", command=show_declaration_pra)
        help_menu.add_command(label="权限声明", command=show_declaration_power)
     
        # 创建“帮助”菜单
        help_menu = tk.Menu(menu_bar, tearoff=0)
        menu_bar.add_cascade(label="帮助", menu=help_menu)
        help_menu.add_command(label="关于", command=show_version1_info)
        help_menu.add_command(label="更多", command=show_version_info)
     
        # 创建“语言”菜单
        help_menu = tk.Menu(menu_bar, tearoff=0)
        menu_bar.add_cascade(label="语言", menu=help_menu)
        help_menu.add_command(label="中文(简体)")
        help_menu.add_command(label="Chinese (Simplified)")
        help_menu.add_command(label="&#51473;&#44397;&#50612; (&#44036;&#52404;)")
        help_menu.add_command(label="Vereinfachtes Chinesisch")
        help_menu.add_command(label="&#1575;&#1604;&#1589;&#1610;&#1606;&#1610;&#1577; &#1575;&#1604;&#1605;&#1576;&#1587;&#1591;&#1577;")
        help_menu.add_command(label="......")
     
        root.mainloop()

     

  • py获取文件后缀

    推荐使用os.path.splitext(file_path),因为这个能够直接获得后缀名,若是自己分割的话,需要考虑文件名中是否有多个.符号

    kimi ai

    在Python中,获取文件的后缀名(扩展名)通常涉及到对文件名进行字符串操作。一个常见的方法是使用os.path.splitext()函数,它能够分割文件名和扩展名。以下是一些获取文件后缀的基本方法:

    使用os.path.splitext()

    import os

    # 假设有一个文件路径
    file_path = 'example.txt'

    # 使用os.path.splitext()获取文件后缀
    _, file_extension = os.path.splitext(file_path)

    print(file_extension) # 输出: .txt

    os.path.splitext()函数返回一个元组,其中第一个元素是文件名(不包含扩展名),第二个元素是文件的扩展名。

    使用字符串方法

    如果你不想使用os.path.splitext(),也可以通过字符串方法来获取文件后缀:

    # 假设有一个文件路径
    file_path = 'example.txt'

    # 字符串方法获取文件后缀
    file_extension = file_path.split('.')[-1] if '.' in file_path else ''

    print(file_extension) # 输出: txt

    这种方法首先检查文件名中是否有.,如果有,就使用split()方法分割字符串,并取最后一个元素作为扩展名。

    使用pathlib模块

    从Python 3.4开始,pathlib模块提供了面向对象的文件系统路径操作方法,也可以方便地获取文件扩展名:

    from pathlib import Path

    # 假设有一个文件路径
    file_path = Path('example.txt')

    # 使用pathlib获取文件后缀
    file_extension = file_path.suffix

    print(file_extension) # 输出: .txt

    Path.suffix属性直接返回文件的扩展名,包括点(.)。

    注意事项

    • 如果文件名中包含多个点,os.path.splitext()pathlib.suffix只会返回最后一个点之后的部分作为扩展名。
    • 如果文件名没有点,os.path.splitext()会返回空字符串,而pathlib.suffix会返回一个空字符串。

    选择哪种方法取决于你的具体需求和Python版本。

  • for /L %i IN (1,1,254) DO ping -w 1 -n 1 192.168.3.%i

    https://jingyan.baidu.com/article/3d69c551251054b1ce02d73e.html

     

    for /L %i IN (1,1,254) DO ping -w 1 -n 1 192.168.3.%i

    以上cmd命令可以ping测试192.168.10网段下的所有ip地址

    也可以把ping -w 1的1改为0.001,这样请求结果会更快

    然后通过arp -a命令查看缓存表有哪些ip地址在线

     

    kimi ai

    这是一条Windows命令提示符(cmd)下的批处理命令,用于对一个指定的子网中的所有可能的IP地址进行ping操作。具体来说,这条命令会尝试ping网段 192.168.3.0192.168.3.255 中的每一个IP地址。下面是命令各部分的详细解释:

    • for /L %i IN (1,1,254):这是一个for循环,/L表示循环变量 %i 将是一个数值。括号中的三个数字分别代表起始值(1)、步长(1)、结束值(254)。这个循环将从1开始,每次增加1,直到254结束。
    • DO:表示对于循环中的每个值,都执行后面的命令。
    • ping:这是Windows系统中用于发送ICMP回显请求的命令,用来检查网络连接是否可达。
    • -w 1-w 参数后面跟的数字表示等待响应的时间,单位是秒。这里设置为1秒,意味着每个ping请求发送后,等待1秒来接收响应。
    • -n 1-n 参数后面跟的数字表示发送的ping请求的次数。这里设置为1,意味着对每个IP地址只发送一次请求。
    • 192.168.3.%i:这是ping命令的目标IP地址。%i 会被循环中的当前数值所替换,因此实际的命令会是 ping -w 1 -n 1 192.168.3.1,然后是 192.168.3.2,依此类推,直到 192.168.3.254

    整个命令的作用是遍历子网 192.168.3.x 中的每个IP地址,发送单个ping请求,以检查哪些设备在线并响应ping。这可以用于快速扫描局域网内的活动设备。

    请注意,这个命令在某些网络环境中可能不被允许,因为它可能会产生大量网络流量,或者被网络管理员视为不安全的行为。此外,一些设备可能由于配置或策略原因,不会响应ping请求。

    kimi ai

    arp -a 是一个在 Windows 命令提示符(cmd)中使用的命令,用于显示当前的ARP(地址解析协议)缓存表。ARP缓存表存储了IP地址到MAC地址的映射关系,这些信息用于在本地网络(局域网)中解析和转发数据包。

    当网络中的设备需要通信时,它们使用ARP来查询其他设备的MAC地址。一旦查询到,该映射关系会被缓存一段时间,以避免重复查询。

    以下是 arp -a 命令的一些关键点:

    • 显示所有ARP条目arp -a 显示当前缓存中的所有ARP条目,包括静态和动态条目。
    • 接口:如果计算机连接到多个网络接口,arp -a 会为每个接口显示ARP缓存。
    • 条目信息:每个条目通常包括IP地址、MAC地址、类型(动态或静态)以及该条目最后被使用的时间。
    • 动态与静态条目:动态条目是自动添加的,当网络通信发生时,而静态条目是手动添加的,用于永久映射特定的IP地址到MAC地址。

    使用示例

    打开命令提示符,然后输入以下命令:

    arp -a

    这将列出所有当前的ARP缓存条目。

    其他ARP命令

    除了 arp -a,还有一些相关的命令用于管理ARP缓存:

    • arp -d:删除指定的ARP缓存条目。
    • arp -s:手动添加静态ARP缓存条目。

    例如,要删除指定的ARP缓存条目,可以使用:

    arp -d IP_ADDRESS

    IP_ADDRESS 替换为要删除的IP地址。

    要添加静态ARP条目,可以使用:

    arp -s IP_ADDRESS MAC_ADDRESS

    IP_ADDRESS 替换为要添加的IP地址,将 MAC_ADDRESS 替换为对应的MAC地址。

    使用这些命令可以帮助你管理网络配置和解决网络问题。

  • flask分页

    <div class="pagination">
      {% if pagination.has_prev %}
          <a href="{{ url_for('search.do_search', page=pagination.prev_num, search=query) }}">上一页</a>
      {% endif %}
      &nbsp;&nbsp;&nbsp;&nbsp;
      {% for page in pagination.iter_pages() %}
          {% if page %}
              {% if page == pagination.page %}
                  <span>{{ page }}</span>
                  &nbsp;&nbsp;&nbsp;&nbsp;
              {% else %}
                  <a href="{{ url_for('search.do_search', page=page, search=query) }}">{{ page }}</a>
                  &nbsp;&nbsp;&nbsp;&nbsp;
              {% endif %}
          {% endif %}
      {% endfor %}
    
      {% if pagination.has_next %}
          <a href="{{ url_for('search.do_search', page=pagination.next_num, search=query) }}">下一页</a>
      {% endif %}
    </div>

     

    kimi ai

    这段代码是一个分页导航的 HTML 模板片段,通常用在 Web 应用中,以便用户可以浏览不同的数据页。它使用了 Flask 的 pagination 对象,这个对象是通过查询集的 paginate 方法生成的。这里使用的是 Jinja2 模板语言,这是 Flask 推荐使用的模板引擎。下面是代码的详细解释:

    1. 分页容器<div class="pagination"> 创建了一个包含所有分页链接的容器,并使用 pagination 类来应用 Bootstrap 的分页样式(假设你正在使用 Bootstrap)。
    2. 上一页链接{% if pagination.has_prev %} 检查是否存在上一页。
      • 如果有上一页,<a href="{{ url_for('search.do_search', page=pagination.prev_num, search=query) }}">上一页</a> 生成一个链接到上一页。url_for 函数用于生成 URL,其中 'search.do_search' 是视图函数的端点名称,page=pagination.prev_num 指定了上一页的页码,search=query 保留了当前搜索查询的参数。
    3. 分页数字{% for page in pagination.iter_pages() %} 循环遍历所有可点击的页码。
      • {% if page %} 确保页码是有效的(非空,非 None)。
      • {% if page == pagination.page %} 检查当前页码,并将其高亮显示(在这里,只是简单地用 <span> 包裹,而不是 <a>)。
      • 如果页码不是当前页,生成一个链接到该页码的 <a> 元素。
      • &nbsp;&nbsp;&nbsp;&nbsp; 表示非断行空格,用于在链接之间添加空间。
    4. 下一页链接{% if pagination.has_next %} 检查是否存在下一页。
      • 如果有下一页,<a href="{{ url_for('search.do_search', page=pagination.next_num, search=query) }}">下一页</a> 生成一个链接到下一页。

    模板变量解释:

    • pagination:由 Flask-SQLAlchemy 的 paginate 方法返回的分页对象,包含了分页信息和方法。
    • pagination.has_prev:布尔值,表示是否有上一页。
    • pagination.prev_num:上一页的页码。
    • pagination.page:当前页码。
    • pagination.iter_pages():生成一个迭代器,包含所有可显示的页码。
    • pagination.has_next:布尔值,表示是否有下一页。
    • pagination.next_num:下一页的页码。

    注意事项:

    • 确保 search 查询参数是从某处获取的,可能是通过 request.args.get('search')
    • url_for 需要与你的路由名称匹配,确保 'search.do_search' 是正确的视图函数名称。
    • 分页导航的样式可以通过 CSS 进一步定制。
    • 如果分页导航没有按预期工作,检查 paginate 方法的调用是否正确,以及 query 参数是否正确传递到视图函数中。

    这段代码是动态生成的,依赖于后端提供的数据和当前用户的请求参数。

  • 使用pywin32库,例如,可以访问Windows的COM接口,如IShellDispatch,来获取文件系统信息

    kimi ai

    使用 pywin32 库来访问 Windows 的 COM 接口,如 IShellDispatch,可以提供一种方法来与 Windows Shell 交互,从而获取文件系统信息。以下是如何使用 pywin32 来实现这一目的的基本步骤:

    1. 安装 pywin32: 首先,确保你已经安装了 pywin32。如果还没有安装,可以通过 pip 安装:
      pip install pywin32
    2. 使用 IShellDispatch 接口IShellDispatch 是 Windows Shell 应用程序接口的一部分,可以用来获取文件和文件夹的信息。
    import win32com.client
    
    # 创建一个 Shell 应用程序的实例
    shell = win32com.client.Dispatch("Shell.Application")
    
    # 获取系统盘的 Folder 项
    system_drive = shell.NameSpace("C:\\")
    
    # 遍历系统盘下的所有项
    for item in system_drive.Items():
        print(f"Name: {item.Name}")
        print(f"Path: {item.Path}")
        print(f"Type: {item.Type}")
        print(f"IsFolder: {item.IsFolder}")
        print("-----")

    输出内容如下(部分):

    Name: application
    Path: C:\application
    Type: 文件夹
    IsFolder: True
    -----
    Name: FPA_OS
    Path: C:\FPA_OS
    Type: 文件夹
    IsFolder: True
    -----
    Name: Genshin Impact Game
    Path: C:\Genshin Impact Game
    Type: 文件夹
    IsFolder: True

     

  • 有什么办法能够让大文件hash快一点吗

    kimi ai

    计算大文件的哈希值时,性能可能会受到文件读取速度和哈希计算速度的影响。以下是一些优化大文件哈希计算速度的方法:

    1. 增加读取块大小:在您的代码中,每次读取文件的块大小是4096字节。您可以尝试增加这个块大小,以减少读取次数。但是要注意不要设置得太大,以免占用过多内存。
    2. 多线程或多进程:如果文件非常大,可以考虑使用多线程或多进程来并行处理文件的不同部分。Python的concurrent.futures模块可以用来实现这一点。
    3. 使用更快的哈希算法:虽然SHA-256是一个广泛使用的算法,但如果您对安全性要求不高,可以考虑使用更快的哈希算法,比如MD5或SHA-1。但请注意,这些算法不再推荐用于需要高安全性的场景。
    4. 优化I/O操作:确保文件系统和存储设备的性能是最优的。例如,使用SSD而不是HDD可以显著提高I/O速度。
    5. 减少日志记录:在处理大文件时,减少或优化日志记录操作,因为日志记录可能会降低性能。
    6. 使用更快的硬件:如果可能的话,使用更快的CPU和更多的RAM可以提高哈希计算的速度。
    7. 避免使用Python的GIL:Python的全局解释器锁(GIL)可能会限制多线程的并行执行。在某些情况下,使用多进程而不是多线程可能会获得更好的性能。
    8. 使用专门的库:有些专门的库可能对哈希计算进行了优化,比如hashlib的某些实现可能比其他实现更快。
    9. 预分配内存:如果使用文件读取函数,预分配足够的内存空间可以减少内存分配的开销。
    10. 避免在循环中打印日志或输出:在循环中打印日志或输出到控制台会显著降低性能,应该尽量避免。

    请注意,即使采取了上述措施,哈希计算仍然是一个计算密集型的任务,特别是对于非常大的文件。您需要在安全性、性能和资源使用之间找到平衡点。

  • #!/usr/bin/python什么意思

    #!/usr/bin/python 是一个称为 shebang 或 hashbang 的特殊行,它通常出现在 Unix 和类 Unix 系统的脚本文件的开头。这个行告诉操作系统,这个脚本应该使用哪个解释器来执行。具体来说,#!/usr/bin/python 表示脚本应该使用位于 /usr/bin/python 路径的 Python 解释器来运行。

    这里是它的一些要点:

    • #!:这个符号叫做 shebang 或 hashbang,是脚本的开始标记。
    • /usr/bin/python:这是 Python 解释器的路径。在不同的系统或环境中,Python 解释器的路径可能不同。

    当你在一个脚本文件的顶部添加了 shebang 行,并且给脚本文件赋予了执行权限(例如,使用 chmod +x script.py 命令),你就可以直接通过在命令行中调用这个脚本文件名来运行它,而不需要指定 Python 解释器的路径。例如:

    ./script.py

    这将执行脚本,就像调用 /usr/bin/python script.py 一样。

    需要注意的是,shebang 行在 Windows 系统中通常不被使用,因为 Windows 使用不同的机制来确定如何执行脚本。此外,如果你的 Python 解释器安装在不同的路径,你需要相应地修改 shebang 行中的路径。例如,如果你使用的是 Python 3,路径可能是 #!/usr/bin/python3

  • flask里面的app.secret_key这个值对于用户有什么影响吗?可以随机吗?

    kimi ai

    在Flask框架中,app.secret_key 是一个重要的配置项,它用于确保应用程序的安全性,尤其是在以下几个方面:

    1. 会话加密:Flask 使用 secret_key 来安全地签名客户端会话。如果攻击者能够预测 secret_key,他们可能会伪造会话,从而绕过身份验证。
    2. CSRF 保护:Flask-WTF 扩展使用 secret_key 来生成 CSRF 令牌,以防止跨站请求伪造攻击。
    3. 密码重置令牌:Flask-Login 等扩展可能使用 secret_key 来生成密码重置令牌,确保重置链接的安全性。
    4. 数据签名:Flask 允许你使用 secret_key 来创建签名的数据,这可以用于确保数据在传输过程中的完整性。
    5. 加密敏感数据:虽然不常见,但 secret_key 有时也用于加密敏感数据。

    对于用户来说,secret_key 的影响通常是间接的,因为它主要用于保护应用程序免受攻击,从而间接保护用户的安全和隐私。用户通常不需要直接与 secret_key 交互,但应该确保应用程序的 secret_key 是安全的,不被泄露给未经授权的人。

     

    如果你正在开发一个 Flask 应用程序,你应该设置一个难以猜测的 secret_key 值,并且不要在公共代码库中暴露它。在生产环境中,你应该使用环境变量或配置文件来安全地存储 secret_key

    app.secret_key 设置为一个完全随机的值是一个非常好的安全实践。以下是一些原因和建议:

    1. 增强安全性:随机生成的 secret_key 难以预测,这增加了破解会话和CSRF令牌的难度。
    2. 防止会话劫持:如果 secret_key 是公开的或容易被猜到的,攻击者可以伪造会话令牌,从而可能劫持用户的会话。
    3. CSRF 保护:随机的 secret_key 有助于生成难以预测的CSRF令牌,从而减少跨站请求伪造攻击的风险。
    4. 密码重置和数据签名:随机的 secret_key 也有助于确保密码重置链接和签名数据的安全性。
    5. 避免硬编码:避免在代码中硬编码 secret_key,而是应该使用环境变量或配置文件来设置它。
    6. 定期更换:虽然随机生成的 secret_key 可以提供很好的安全性,但定期更换 secret_key 也是一个好习惯,特别是如果你怀疑它可能已经被泄露。
    7. 使用强随机数生成器:确保使用加密安全的随机数生成器来生成 secret_key,以避免使用可能不够安全的伪随机数生成器。

    在Flask中,你可以使用Python的 os.urandom() 函数来生成一个随机的密钥:

    python
    import os
    app.secret_key = os.urandom(24)

    这将生成一个24字节的随机密钥,足以满足大多数安全需求。记得将这个密钥保存在安全的地方,比如环境变量中,以避免在代码库中暴露它。

  • py文件hash

    import hashlib
    def 计算文件hash值(文件绝对路径):
        '''
        输出了64字节长度的字符
        关于hashlib详见:
        https://www.runoob.com/python3/python-hashlib.html
        '''
        hash_func = hashlib.sha256()
        try:
            with open(文件绝对路径, 'rb') as f:
                for chunk in iter(lambda: f.read(4096), b""):
                    hash_func.update(chunk)
            return hash_func.hexdigest()
        except IOError as e:  # 捕获文件读取错误
            flash('读取文件时发生IO错误:' + str(e))
            current_app.logger.warning('读取文件时发生IO错误:' + str(e))
            return None

     

    这段Python代码是一个用于计算文件SHA-256哈希值的函数。SHA-256是一种加密哈希函数,常用于验证文件的完整性。下面是这段代码的详细解释:

    1. hash_func = hashlib.sha256(): 这行代码初始化了一个SHA-256哈希对象。hashlib 是Python中用于哈希算法的库,sha256 是其中一种算法。
    2. try:: 这是一个异常处理的开始,try块中的代码将尝试执行,如果发生异常,将跳转到except块。
    3. with open(文件绝对路径, 'rb') as f:: 使用with语句打开一个文件,文件绝对路径需要替换成实际的文件路径。'rb'表示以二进制读取模式打开文件。as f将文件对象赋值给变量f
    4. for chunk in iter(lambda: f.read(4096), b""):: 这是一个循环,使用iter函数和lambda匿名函数创建一个迭代器,每次从文件中读取4096字节的数据(一个chunk),直到文件结束(即f.read(4096)返回空字节串b"")。
    5. hash_func.update(chunk): 将读取的文件块(chunk)的数据更新到哈希对象中。SHA-256算法是逐步处理数据的,所以需要在读取每个块后更新哈希状态。
    6. return hash_func.hexdigest(): 在循环结束后,返回哈希对象的十六进制摘要字符串。hexdigest方法将内部的哈希值转换为十六进制格式的字符串。
    7. except IOError as e:: 如果在尝试打开或读取文件时发生IO错误(例如文件不存在或权限问题),这行代码会捕获这个异常。
    8. flash('读取文件时发生IO错误:' + str(e)): 这行代码可能是用于Web应用中的一个函数,用于显示一个flash消息,告知用户发生了IO错误,并显示错误信息。
    9. current_app.logger.warning('读取文件时发生IO错误:' + str(e)): 这行代码记录了一个警告级别的日志,包含了发生的错误信息。current_app是一个Flask应用的引用,logger是其日志记录器。
    10. return None: 如果发生异常,函数将返回None,表示没有成功计算出哈希值。

    请注意,这段代码中有几个地方需要根据实际情况进行修改:

    • 文件绝对路径需要替换成实际的文件路径。
    • flashcurrent_app.logger的使用依赖于特定的Web框架(如Flask),如果你不是在Web应用中使用这段代码,可能需要替换或删除这些行。