Mask or redirect console window of external program

Hi,

Config :
Win10x64
Pyhton3.6x32
WxPython 4.0.6

I’m writing a wxPython app that uses of a library which runs external programs.
All is fine.
When I freeze my app (with cxfreeze), I see console windows opening and closing. I can reproduce the problem without freezing my app when running it with pythonw.
I search the Internet but didn’t find any solution.
How can I get rid of these console windows ?

Regards,
Nicolas

Try adding console=False to the EXE constructor in your spec file. See https://pythonhosted.org/PyInstaller/operating-mode.html#using-a-console-window

There’s no such option with cxfreeze. However, I use base = "Win32GUI". This let remove the console window of the wx app.
To be clear, the problem is not with the console window associated to the wx app. The problem is with console windows created when external programs are run from the wx app.

Here is an example :

import wx
import threading
import os

USE_THREAD = True

class Principale(wx.Frame):
    def __init__(self, titre):
        wx.Frame.__init__(self, None, -1, title = titre, size = (200, 200))

        self.button = wx.Button(self, wx.ID_ANY, "timeout")
        self.button.Bind(wx.EVT_BUTTON, self._on_click)

    def _on_click(self, event):
        if USE_THREAD :
            ThreadedTimeout()
        else :
            print("Start timeout")
            os.system("timeout 5")
            print("timeout done")
        event.Skip(True)

class ThreadedTimeout(threading.Thread) :
    def __init__(self) :
        super().__init__()
        self.start()
    def run(self):
        print("Start timeout")
        os.system("timeout 5")
        print("timeout done")

class MonApp(wx.App):
    def OnInit(self):
        fen = Principale("Test")
        fen.Show(True)
        self.SetTopWindow(fen)
        return True

app = MonApp(0)
app.MainLoop()

When the console window associated with the wx app is not discarded, children processes send their output in this console and no other console window is created.
When the console window associated with the wx app is discarded (when freezed or run with pythonw), a new console window is created for each child process.
What I what to achieve is to discard all console windows.

wxPbConsole.py (991 Bytes)

If you use the subprocess module you can do exactly that - I use it all the time for long running tasks:

Andrea.

Unfortunately, the external program launches are done by a third party library. I have no control on it.

One solution might be to create a console window with wxPython API, attach it to the wx app and hide it. This way, children processes would direct their outputs to this hidden console window. But is this possible ?

I don’t understand: are you or are you not starting this third-party app? Your code sample simply calls “os.system”…
If you are starting this third party app then I would start it in a separate thread that starts a process using subprocess as I mentioned before. Otherwise my apologies as I have probably not understood your problem correctly.

Andrea.

My example is a very simple example to be run as is, without dependencies.
In fact, I use a third party library (youtube-dl) which runs external processes.

I found an acceptable solution.

The problem is that external programs are run from a library I have no control on. These external programs either use their parent console, or create a new one if the parent has no console.
Running a wx app in base mode creates a console that is used by children processes.
Running a wx app in gui mode discards the app console. As a consequence, children processes create their own console.
In both cases, console windows are created (and visible).

My work around is to run my wx app in base mode and hide the console window.
Here is how to do that :

    # Hide console window
    import ctypes
    SW_HIDE = 0;
    SW_SHOW = 5;
    cw = ctypes.windll.kernel32.GetConsoleWindow()
    ctypes.windll.user32.ShowWindow(cw, SW_HIDE)

This way, when the frozen wx app is launched, the console window is shown for some time (depending on app startup duration) and hidden by the app. Children processes attach to this hidden console so no new console is created when they are run.

This is not ideal but I can live with it.