使用pywinauto import冻结tkinter

时间:2018-06-24 17:16:11

标签: python-3.x tkinter freeze pywinauto

问题:
当我单击运行的按钮时,我的python gui(tkinter)被冻结:
filename = filedialog.askdirectory()
当我在另一个脚本中使用from pywinauto import application时,只会发生 。如果我注释掉pywinauto导入,askdirectory可以正常工作。没有冻结,窗口将按预期方式弹出。发生这种情况时,我看不到任何错误。

很抱歉,长期以来,我想提供尽可能多的细节。让我知道是否需要更多以及您正在寻找什么。理想情况下,我想使用askdirectory,但是我认为我可以只使用askopenfilename来获取该目录。

Python版本:
Python 3.4.4

Windows版本:
Windows Server 2012 R2(无法更改)

我尝试过的事情
1.通过教程进行基本线程处理(每次仍然冻结,底部的代码示例)
2.注释掉部分代码以缩小问题范围。
3.尝试通过PyCharms调试器进行调试,但是如果出现错误,则看不到它。
4.不同的IDE。

  • IDLE =失败
  • Pycharm =失败(据我所知,解释器与空闲状态相同,因此不足为奇)
  • Pythonwin =很好用)

  • 以下代码块:
    如果您愿意的话,我将这些代码块按照它们之间的交互顺序放在下面。它从第一个开始,然后到第二个(中间),最后到第三个。

    问题:
    我有办法检查错误吗? 我在这里做错了什么导致这种情况发生吗? 为什么askopenfilename可以正常工作,而不是askdirectory?

    包含冻结窗口的文件:

    from InstallMenu import MainMenu
    from tkinter import *
    from tkinter import filedialog
    
    """
    This is where it freezes.  If I change askdirectory to openaskfilename it 
    works without any issues.  If I comment out the from pywinauto import 
    application from opusite.py, askdirectory works without issue.
    """
    def chooseInstallFolder(installFolderPath):
        filename = filedialog.askdirectory()
        installFolderPath.config(text=filename)
    
    def submitFolder(installFolderApp, installFolderPath, setObj):
        installFolderApp.destroy()
        MainMenu(installFolderPath, setObj)
    
    def chooseInstall(setObj):
        installFolderApp = Tk()
        installFolderApp.title("Find Install Folder")
        installFolderApp.geometry("300x200")
    
        #Gui items
        pickAFolder = Label(installFolderApp, text = "Select your Install Folder")
        pickInstallerButton = Button(installFolderApp, text="Browse", command = lambda : chooseInstallFolder(installFolderPath))
        installFolderPath = Label(installFolderApp, text = " ")
        submit = Button(installFolderApp, text="Submit", command = lambda : submitFolder(installFolderApp, installFolderPath, setObj))
    
        #Packing
        pickAFolder.pack()
        installFolderPath.pack()
        pickInstallerButton.pack()
        submit.pack()
    
        installFolderApp.mainloop()
    

    上面的“提交”按钮的菜单脚本进入:
    我已经注释掉iParcPro,因为它使用了导致冻结的相同导入。

    import opusite
    #from iParcPro import *
    from Sql import *
    from tkinter import *
    
    def OPUSiteInstall(installFolderPath):
        opusite.OPUSiteInstall(installFolderPath, setObj)
        opusite.rs485Install(installFolderPath, setObj)
    
    def MainMenu(installFolderPath, setObj):
        menuWindow = Tk()
        menuWindow.title("Auto Installer Menu")
        menuWindow.geometry("325x250")
    
        #Create variables
        ChooseAButton = Label(menuWindow, text = "Choose an option")
    
        OPUSiteButton = Button(menuWindow, text="OPUSite Install", height = 1, 
        width 
        = 15, command = lambda : OPUSiteInstall(installFolderPath, setObj))
    
        #Pack
        ChooseAButton.pack()
        OPUSiteButton.pack()
    
        menuWindow.mainloop()
    

    包含似乎冻结了此导入的代码:

    import pyautogui as ag
    """
    This import here freezes it.  If I comment out just the import, the 
    askdirectory works fine.
    """
    from pywinauto import application
    
    def OPUSiteInstall(installFolderPath, setObj):
        path = installFolderPath + '\\OPUSite\\AMI.OPUSite.Setup.msi'
        app = application.Application().Start(r'msiexec.exe /i ' + path)
        Wizard = app['OPUSite Setup']
        Wizard.NextButton.Wait('enabled', 50000)
        Wizard.NextButton.Click()
        Wizard['I &accept the terms in the License 
        Agreement'].Wait('enabled').CheckByClick()
        Wizard.NextButton.Click()
        Wizard.NextButton.Click()
        ag.typewrite(setObj.databaseName)
        ag.press('tab')
        ag.press('space')
        ag.press('tab')
        ag.press('tab')
        ag.typewrite(setObj.password)
        ag.press('tab')
        ag.typewrite(setObj.password)
        ag.press('tab')
        ag.typewrite(setObj.password)
        Wizard.NextButton.Click()
        Wizard.Install.Click()
    
        Wizard.Finish.Wait('visible', 50000)
        Wizard.Finish.Click()
    
    def rs485Install(installFolderPath, setObj):
        path = installFolderPath + '\\OPUSite\\AMI.RS485AdapterSvc.Setup.msi'
        app = application.Application().Start(r'msiexec.exe /i ' + path)
        Wizard = app['RS485Adapter Setup']
        Wizard.NextButton.Wait('enabled', 50000)
        Wizard.NextButton.Click()
        Wizard['I &accept the terms in the License 
        Agreement'].Wait('enabled').CheckByClick()
        Wizard.NextButton.Click()
        Wizard.NextButton.Click()
        Wizard.Install.Click()
    
        Wizard.Finish.Wait('visible', 50000)
        Wizard.Finish.Click()
    

    这是我尝试过的穿线衣服。没用:

    from InstallMenu import MainMenu
    from tkinter import *
    from tkinter import filedialog
    import threading
    
    def chooseInstallFolder(installFolderPath):
        def callback(installFolderPath):
            filename = filedialog.askdirectory()
            installFolderPath.config(text=filename)
        t = threading.Thread(target=callback, args=(installFolderPath,))
        t.start()
    
    def submitFolder(installFolderApp, installFolderPath, setObj):
        installFolderApp.destroy()
        MainMenu(installFolderPath, setObj)
    
    def chooseInstall(setObj):
        installFolderApp = Tk()
        installFolderApp.title("Find Install Folder")
        installFolderApp.geometry("300x200")
    
        #Gui items
        pickAFolder = Label(installFolderApp, text = "Select your Install 
        Folder")
        pickInstallerButton = Button(installFolderApp, text="Browse", command = 
        lambda : chooseInstallFolder(installFolderPath))
        installFolderPath = Label(installFolderApp, text = " ")
        submit = Button(installFolderApp, text="Submit", command = lambda : 
        submitFolder(installFolderApp, installFolderPath, setObj))
    
        #Packing
        pickAFolder.pack()
        installFolderPath.pack()
        pickInstallerButton.pack()
        submit.pack()
    
        installFolderApp.mainloop()
    

    2 个答案:

    答案 0 :(得分:1)

    我能够解决这个问题。我想指出的是,我仍然不确定为什么这样做。我所做的就是将pywinauto导入移至我的函数中,现在askdirectory运行正常。

    import pyautogui as ag
    
    def OPUSiteInstall(installFolderPath, setObj):
        from pywinauto import application
        path = installFolderPath + '\\OPUSite\\AMI.OPUSite.Setup.msi'
        app = application.Application().Start(r'msiexec.exe /i ' + path)
        Wizard = app['OPUSite Setup']
        Wizard.NextButton.Wait('enabled', 50000)
        Wizard.NextButton.Click()
        Wizard['I &accept the terms in the License 
        Agreement'].Wait('enabled').CheckByClick()
        Wizard.NextButton.Click()
        Wizard.NextButton.Click()
        ag.typewrite(setObj.databaseName)
        ag.press('tab')
        ag.press('space')
        ag.press('tab')
        ag.press('tab')
        ag.typewrite(setObj.password)
        ag.press('tab')
        ag.typewrite(setObj.password)
        ag.press('tab')
        ag.typewrite(setObj.password)
        Wizard.NextButton.Click()
        Wizard.Install.Click()
    
        Wizard.Finish.Wait('visible', 50000)
        Wizard.Finish.Click()
    
    def rs485Install(installFolderPath, setObj):
        from pywinauto import application
        path = installFolderPath + '\\OPUSite\\AMI.RS485AdapterSvc.Setup.msi'
        app = application.Application().Start(r'msiexec.exe /i ' + path)
        Wizard = app['RS485Adapter Setup']
        Wizard.NextButton.Wait('enabled', 50000)
        Wizard.NextButton.Click()
        Wizard['I &accept the terms in the License 
        Agreement'].Wait('enabled').CheckByClick()
        Wizard.NextButton.Click()
        Wizard.NextButton.Click()
        Wizard.Install.Click()
    
        Wizard.Finish.Wait('visible', 50000)
        Wizard.Finish.Click()
    `
    

    答案 1 :(得分:1)

    遇到了同样的问题,并在下面找到了解决方法

    https://github.com/pywinauto/pywinauto/issues/517 https://pywinauto.readthedocs.io/en/latest/HowTo.html#com-threading-model

    import sys
    sys.coinit_flags = 2  # COINIT_APARTMENTTHREADED
    import pywinauto