吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 472|回复: 3
收起左侧

[经验求助] Python 打包exe 启动后 无限重复打开

[复制链接]
倔强的阿飞 发表于 2024-7-13 10:52
50吾爱币
求解决如题问题,打开exe执行以后 无限打开窗口。 求原因和解决方案  下面是代码

[PHP] 纯文本查看 复制代码
import webview
import threading
import time
from pystray import Icon, Menu, MenuItem
from PIL import Image, ImageDraw
import pygetwindow as gw
import multiprocessing
from printer_monitor import start_monitoring_all_printers
import win32api
import win32con
import win32gui
import os
import webbrowser

url = 'https://www.baidu.com'


def exit_program():
    os._exit(0)


def on_click(icon, item):
    window.show()

def create_tray_icon():
    # image = create_image(64, 64, 'black', 'white')
    image = Image.open('./favicon.ico')
    menu = Menu(
        MenuItem('打印计费系统', on_click),
        MenuItem('后台登录', open_url)
    )
    icon = Icon("test", image, "打印计费系统", menu)
    icon.run()
def open_url(icon, item):
    webbrowser.open('https://www.baidu.com')
def hide_window_after_delay(window):
    time.sleep(1)
    result = window.evaluate_js('localStorage.getItem("isLogin")')
    if result == 'true':
        window.hide()
    else:
        hide_window_after_delay(window)

def move_to_bottom_right(window_title="打印计费系统"):
    max_attempts = 10
    attempt = 0
    hwnd = None

    while attempt < max_attempts:
        window = gw.getWindowsWithTitle(window_title)
        if window:
            hwnd = window[0]._hWnd
            if hwnd:
                break
        attempt += 1
        time.sleep(1)  # 等待窗口创建完成

    if hwnd:
        # 获取屏幕的宽度和高度
        screen_width = win32api.GetSystemMetrics(win32con.SM_CXSCREEN)
        screen_height = win32api.GetSystemMetrics(win32con.SM_CYSCREEN)

        # 获取窗口大小
        rect = win32gui.GetWindowRect(hwnd)
        window_width = rect[2] - rect[0]
        window_height = rect[3] - rect[1]

        # 设置窗口位置为右下角
        new_x = screen_width - window_width
        new_y = screen_height - window_height

        win32gui.MoveWindow(hwnd, new_x, new_y, window_width, window_height, True)
    else:
        print("Failed to get window handle.")
def process_print_jobs(queue, window):
    while True:
        job = queue.get()
        if job is None:
            break

        # 修改字段名称并构造新的字典
        processed_job = {
            "job_id": job['Job ID'],
            "document_name": job['Document'],
            "paper_type": "普通纸",  # 根据纸张尺寸决定纸质类型
            "size": f"{job['Paper Size']}",  # 如果纸张尺寸不是A4则显示具体尺寸
            "color_mode": job['Color'],
            "type": "单面" if job['Duplex'] == 1 else "双面",  # 类型可以根据具体业务逻辑设置
            "total_pages": job['Pages'],
            "copies": job['Copies'] , # 分数修改为份数
        }
        # 将处理后的任务传入 JavaScript 中
        window.evaluate_js(f'addLocalItem({processed_job})')
        window.show()
        move_to_bottom_right()

if __name__ == "__main__":
    job_queue = multiprocessing.Queue()

    # 启动监控进程
    monitor_process = multiprocessing.Process(target=start_monitoring_all_printers, args=(job_queue,))
    monitor_process.start()

    # 创建并显示窗口
    window = webview.create_window('打印计费系统', url, width=680, height=450, confirm_close=True, resizable=False, on_top=True)
    # 监听窗口关闭事件
    window.events.closed += exit_program
    # 在另一个线程中运行隐藏窗口的函数
    t1 = threading.Thread(target=hide_window_after_delay, args=(window,))
    t1.start()

    # 创建并启动线程来监控窗口状态
    t2 = threading.Thread(target=process_print_jobs, args=(job_queue, window))
    t2.start()

    # 创建并启动托盘图标线程
    t3 = threading.Thread(target=create_tray_icon)
    t3.start()

    # 启动 PyWebView
    chinese = {
        'global.quitConfirmation': u'确定关闭?',
    }
    webview.start(localization=chinese)

最佳答案

查看完整内容

问了下chatglm[md]根据你提供的代码,我将进行一些修改以解决可能的问题。以下是修改后的代码: ```python import webview import threading import time from pystray import Icon, Menu, MenuItem from PIL import Image import pygetwindow as gw import multiprocessing from printer_monitor import start_monitoring_all_printers import win32api import win32con import win32gui import os import webbrows ...

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

collinchen1218 发表于 2024-7-13 10:52
问了下chatglm

根据你提供的代码,我将进行一些修改以解决可能的问题。以下是修改后的代码:

import webview
import threading
import time
from pystray import Icon, Menu, MenuItem
from PIL import Image
import pygetwindow as gw
import multiprocessing
from printer_monitor import start_monitoring_all_printers
import win32api
import win32con
import win32gui
import os
import webbrowser
url = 'https://www.baidu.com'
def exit_program():
    os._exit(0)
def on_click(icon, item):
    window.show()
def create_tray_icon():
    image = Image.open('./favicon.ico')
    menu = Menu(
        MenuItem('打印计费系统', on_click),
        MenuItem('后台登录', open_url)
    )
    icon = Icon("test", image, "打印计费系统", menu)
    icon.run()
def open_url(icon, item):
    webbrowser.open('https://www.baidu.com')
def hide_window_after_delay(window):
    while True:
        time.sleep(1)
        result = window.evaluate_js('localStorage.getItem("isLogin")')
        if result == 'true':
            window.hide()
            break
def move_to_bottom_right(window_title="打印计费系统"):
    max_attempts = 10
    attempt = 0
    hwnd = None
    while attempt < max_attempts:
        window = gw.getWindowsWithTitle(window_title)
        if window:
            hwnd = window[0]._hWnd
            if hwnd:
                break
        attempt += 1
        time.sleep(1)
    if hwnd:
        screen_width = win32api.GetSystemMetrics(win32con.SM_CXSCREEN)
        screen_height = win32api.GetSystemMetrics(win32con.SM_CYSCREEN)
        rect = win32gui.GetWindowRect(hwnd)
        window_width = rect[2] - rect[0]
        window_height = rect[3] - rect[1]
        new_x = screen_width - window_width
        new_y = screen_height - window_height
        win32gui.MoveWindow(hwnd, new_x, new_y, window_width, window_height, True)
    else:
        print("Failed to get window handle.")
def process_print_jobs(queue, window):
    while True:
        job = queue.get()
        if job is None:
            break
        processed_job = {
            "job_id": job['Job ID'],
            "document_name": job['Document'],
            "paper_type": "普通纸",
            "size": f"{job['Paper Size']}",
            "color_mode": job['Color'],
            "type": "单面" if job['Duplex'] == 1 else "双面",
            "total_pages": job['Pages'],
            "copies": job['Copies'],
        }
        window.evaluate_js(f'addLocalItem({processed_job})')
        window.show()
        move_to_bottom_right()
if __name__ == "__main__":
    if not is_already_running():
        job_queue = multiprocessing.Queue()
        monitor_process = multiprocessing.Process(target=start_monitoring_all_printers, args=(job_queue,))
        monitor_process.start()
        window = webview.create_window('打印计费系统', url, width=680, height=450, confirm_close=True, resizable=False, on_top=True)
        window.events.closed += exit_program
        t1 = threading.Thread(target=hide_window_after_delay, args=(window,))
        t1.start()
        t2 = threading.Thread(target=process_print_jobs, args=(job_queue, window))
        t2.start()
        t3 = threading.Thread(target=create_tray_icon)
        t3.start()
        webview.start(localization={'global.quitConfirmation': u'确定关闭?'})
def is_already_running():
    import socket
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    result = sock.connect_ex(('127.0.0.1', 54321))
    if result == 0:
        return True
    else:
        sock.bind(('127.0.0.1', 54321))
        return False

这里做了以下修改:

  1. 添加了 is_already_running 函数,在 if __name__ == "__main__": 块开始时调用,以防止程序多次运行。
  2. 修改了 hide_window_after_delay 函数,使其在检测到登录后退出循环,避免无限递归调用。
  3. create_tray_icon 函数中的 MenuItemon_click 方法直接设置为 window.show(),避免不必要的回调。
    在重新打包程序之前,请确保已经安装了所有必要的依赖项,并且正确设置了 PyInstaller 的 .spec 文件。如果问题仍然存在,可能需要进一步调试或检查 PyInstaller 的日志输出以获取更多信息。
已经好晕了 发表于 2024-7-13 11:30
Python 打包成exe后出现无限重复打开窗口的问题,可能由多种原因引起。以下是一些可能的原因和相应的解决方案:

全局变量问题:如果程序中使用了全局变量,并且在多线程环境中没有正确地管理这些变量,可能会导致程序的异常行为。

线程同步问题:如果使用了多线程,确保线程间的同步机制正确实现,避免竞态条件。

循环引用问题:检查代码中是否有循环引用,特别是在GUI应用程序中,循环引用可能导致程序无法正确关闭。

事件处理问题:检查事件处理函数,确保它们不会触发自身再次执行。

打包工具问题:打包成exe的过程中可能引入了问题。确保使用的打包工具(如PyInstaller)是最新版本,并且按照正确的步骤进行打包。

依赖问题:确保所有依赖库都已正确安装,并且与Python版本兼容。

操作系统问题:操作系统的某些设置或权限问题可能导致程序无法正常关闭。

代码逻辑问题:检查代码逻辑,特别是与窗口创建和关闭相关的部分。

针对您提供的代码,以下是一些具体的检查点和建议:

检查webview.create_window调用是否可能被多次触发。
确保exit_program函数能够正确终止所有线程和子进程。
检查process_print_jobs函数中的while True:循环,确保queue.get()在队列为空时能够正确退出。
检查move_to_bottom_right函数是否可能被多次调用,导致窗口位置不断变化。
解决方案示例:
[Python] 纯文本查看 复制代码
# 在process_print_jobs函数中添加退出条件
def process_print_jobs(queue, window):
    while True:
        job = queue.get()  # 使用阻塞调用,直到队列为空
        if job is None:
            break
        # ... 处理作业 ...

        # 仅在有作业处理时显示窗口
        if job:
            window.show()
            move_to_bottom_right()

    # 处理完所有作业后退出
    window.close()
    exit_program()
Arcticlyc 发表于 2024-7-13 11:42
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2024-12-16 04:02

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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