Pysimplegui: [PyInstaller 问题] 调用子进程时执行脚本失败

创建于 2019-10-17  ·  4评论  ·  资料来源: PySimpleGUI/PySimpleGUI

问题类型

漏洞

操作系统

Windows 7的

蟒蛇版本

3.5

PySimpleGUI 端口和版本

4.4.1

您数月或数年的经验水平

Python编程经验
1

总体编程经验
7

以前使用过另一个 Python GUI 框架(tkiner、Qt 等)(是/否很好)?
是的

您已完成以下步骤:

  • [是]阅读有关如何提交问题的说明
  • [是] 通过主要文档http://www.PySimpleGUI.org搜索您的问题
  • [ ] 如果不是 PySimpleGUI(Qt、WX、Remi),则在自述文件中搜索您的特定端口
  • [ ] 寻找与您的目标相似的演示程序http://www.PySimpleGUI.com
  • [ ] 注意GitHub上每个端口下也有Demo Programs
  • [是] 在调试器之外运行程序(从命令行)
  • [是] 搜索问题(打开和关闭)以查看是否已报告

导致问题的代码或部分代码

我是 PySimpleGUI 的新手。 当我使用模块子进程并将 py 打包成 exe 时,它​​总是像下面的截图一样崩溃。 但是当我直接在cmd中运行我的py文件时,就很好了。 所以有人请告诉我如何解决它? 谢谢。

单击确定时,Windows7 上的 exe 文件崩溃:
enter image description here

SimpleDemoTestSubprocess.py:

import PySimpleGUI as sg
import subprocess


def runCommand(cmd, timeout=None):
    """ run shell command
    <strong i="38">@param</strong> cmd: command to execute
    <strong i="39">@param</strong> timeout: timeout for command execution
    <strong i="40">@return</strong>: (return code from command, command output)
    """

    prt('runCommand, cmd = ' + str(cmd))

    p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    output = ''

    prt('runCommand, communicate')
    out, err = p.communicate()
    prt('runCommand, wait')
    p.wait(timeout)

    prt(out)
    prt(err)

    return (out, err)


def prt(self, *args, sep=' ', end='\n', file=None):
    print()
    print(self, *args, sep=' ', end='\r\n', file=None)


# All the stuff inside your window.
layout = [
    [sg.Text('Some text on Row 1')]
    , [sg.Text('Enter something on Row 2'), sg.InputText()]
    , [sg.Button('Ok'), sg.Button('Cancel')]
    # , [sg.PopupScrolled('Hello From PySimpleGUI!', 'This is the shortest GUI program ever!')]
]

# Create the Window
window = sg.Window('Window Title', layout)
# Event Loop to process "events" and get the "values" of the inputs
while True:
    event, values = window.read()
    if event in (None, 'Cancel'):  # if user closes window or clicks cancel
        break
    if event in (None, 'Ok'):  # if user closes window or clicks cancel
        runCommand("ls")
    print('You entered ', values[0])

window.close()

将py打包成exe:

# https://github.com/PySimpleGUI/PySimpleGUI/blob/master/DemoPrograms/Demo_EXE_Maker.py

import PySimpleGUI as sg
import subprocess
from shutil import copyfile
import shutil
import os

def prt(self, *args, sep=' ', end='\n', file=None):
    print()
    print(self, *args, sep=' ', end='\r\n', file=None)

def Launcher():
    sg.ChangeLookAndFeel('LightGreen')

    layout = [[sg.T('PyInstaller EXE Creator', font='Any 15')],
              [sg.T('Source Python File'), sg.In(key='_sourcefile_', size=(45, 1)),
               sg.FileBrowse(file_types=(("Python Files", "*.py"),))],
              [sg.T('Icon File'), sg.In(key='_iconfile_', size=(45, 1)),
               sg.FileBrowse(file_types=(("Icon Files", "*.ico"),))],
              [sg.Frame('Output', font='Any 15', layout=[[sg.Output(size=(65, 15), font='Courier 10')]])],
              [sg.ReadFormButton('Make EXE', bind_return_key=True),
               sg.SimpleButton('Quit', button_color=('white', 'firebrick3')), ]]

    window = sg.Window('PySimpleGUI EXE Maker',
                       auto_size_text=False,
                       auto_size_buttons=False,
                       default_element_size=(20, 1,),
                       text_justification='right')

    window.Layout(layout)

    # ---===--- Loop taking in user input --- #
    while True:
        (button, values) = window.Read()
        if button in ('Quit', None):
            break  # exit button clicked

        source_file = values['_sourcefile_']
        icon_file = values['_iconfile_']

        icon_option = '-i "{}"'.format(icon_file) if icon_file else ''
        source_path, source_filename = os.path.split(source_file)
        workpath_option = '--workpath "{}"'.format(source_path)
        dispath_option = '--distpath "{}"'.format(source_path)
        specpath_option = '--specpath "{}"'.format(source_path)
        folder_to_remove = os.path.join(source_path, source_filename[:-3])
        file_to_remove = os.path.join(source_path, source_filename[:-3] + '.spec')
        command_line = 'pyinstaller -wF "{}" {} {} {} {}'.format(source_file, icon_option, workpath_option,
                                                                 dispath_option, specpath_option)

        if button == 'Make EXE':
            try:
                prt('source_file: ' + str(source_file))
                prt('Making EXE... this will take a while.. the program has NOT locked up...')
                window.Refresh()

                prt('window.Refresh')
                window.Refresh()
                prt('Running command: {}'.format(command_line))
                runCommand(command_line)
                shutil.rmtree(folder_to_remove)
                os.remove(file_to_remove)
                prt('**** DONE ****')
            except Exception as e:
                # sg.PopupError('Something went wrong')
                prt("Launcher, Exception = " + e)


def runCommand(cmd, timeout=None):
    """ run shell command
    <strong i="6">@param</strong> cmd: command to execute
    <strong i="7">@param</strong> timeout: timeout for command execution
    <strong i="8">@return</strong>: (return code from command, command output)
    """

    prt('runCommand, cmd = ' + str(cmd))

    p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    output = ''

    prt('runCommand, communicate')
    out, err = p.communicate()
    prt('runCommand, wait')
    p.wait(timeout)

    prt(out)
    prt(err)

    return (out, err)

if __name__ == '__main__':
    Launcher()

最有用的评论

通过改变这个来解决:

p = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.STDOUT,stdin=subprocess.PIPE)

所有4条评论

这是 PyInstaller 的一个问题。 如果您不将其转换为 EXE 文件,我认为一切运行良好。 过去,由于 PyInstaller 问题,我无法将您在 GitHub 上找到的启动器演示程序转换为 EXE 文件。

我建议在 subprocess 调用和 PyInstaller 的更一般的问题上检查 stackoverflow 或其他地方。

如果你去掉所有的 PySimpleGUI 代码,只从你的 EXE 文件中调用子进程调用,那有问题吗? 您可以尝试对其进行硬编码并运行测试吗?

“如果你不把它变成 EXE 文件,我认为一切都运行良好”
是的。

“如果你去掉所有的 PySimpleGUI 代码,只从你的 EXE 文件中调用子进程调用,那会有问题吗?”
好的,我删除了所有 PySimpleGUI 代码,但它仍然崩溃。 所以它与 PySimpleGUI 无关 :)

那么 PySimpleGUI 是否支持其他 EXE 打包程序,而不是 pyinstaller?

通过改变这个来解决:

p = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.STDOUT,stdin=subprocess.PIPE)

谢谢!!!!!!!!!

我一直在尝试解决这个问题一段时间。 我非常感谢您不仅挖掘并找到解决方案,而且还回来并发布它。 非常感激!

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

MikeTheWatchGuy picture MikeTheWatchGuy  ·  6评论

flowerbug picture flowerbug  ·  4评论

martinmeteor picture martinmeteor  ·  4评论

mozesa picture mozesa  ·  4评论

yogesh-aggarwal picture yogesh-aggarwal  ·  3评论