Search code examples
pythonpython-3.xcx-freeze

subprocess.Popen behavior after cx_freeze


I have some python code using subprocess.Popen to open a console application and get stdout/stderr from it.

Launching from the interpreter works fine and as intended.

After using cx_freeze with --base-name Win32GUI option the Popen pops up in a console window now and I can't capture stdout/stderr. If I remove --base-name Win32GUI it works as intended but I now have a console behind the UI.

Here is the code (I've tried it without startupinfo and without shell=False):

startupinfo = subprocess.STARTUPINFO()
            startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
            startupinfo.wShowWindow = subprocess.SW_HIDE
subprocess.Popen(['exe', 'arg1', 'arg2'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False, startupinfo=startupinfo)

I'm using out, err = p.communicate() to grab stdout/stderr


Solution

  • Okay I found a solution. It looks like since its a windows GUI Application stdout handle doesn't exist and it looks like subprocess inherits that behavior. So a workaround is a simple one and a more complicated one involved with the win32api and creating a pipe for it (didn't try this method).

    Here is what finally worked:

    startupinfo = subprocess.STARTUPINFO()
                startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
                startupinfo.wShowWindow = subprocess.SW_HIDE
    stdout_file = tempfile.NamedTemporaryFile(mode='r+', delete=False)
    process = subprocess.Popen(['exe', 'arg1', 'arg2'], stdin=subprocess.PIPE, stdout=stdout_file, stderr=subprocess.PIPE, shell=False, startupinfo=startupinfo)
    return_code = process.wait()
    stdout_file.flush()
    stdout_file.seek(0) # This is required to reset position to the start of the file
    out = stdout_file.read()
    stdout_file.close()