Search code examples
pythontkinterconsolecx-freeze

Converting a tkinter/selenium app into an .exe via cx_freeze; Console-problem


I need help with cx_freeze but it also implies some tkinter (and selenium but none at the point of failure). I am actively searching the internet but this edge-case is probably extremely specific. I have posted the parts that i hope and think are the relevant ones, i can't post everything, it's very long and i'd have to censor enough for it to be a full time job for a day.

the problem is the following:

when i compile with cx_freeze on windows with base="Win32GUI" no part of the test_start module is executed on button-press. If I compile with base=None everything works.

the cx_freeze file:

from cx_Freeze import setup, Executable

executables = [Executable("gui.py", base="Win32GUI", target_name="TestingClient", icon=r".\test2.ico")]

packages = ["selenium", "time", "tkinter", "json", "random", "sys", "threading", "functools", "datetime", "traceback",
            "contextlib", "webdriver_manager.chrome"]

includes = ["test_start", "testing_lib", "__init__", "module_whose_name_i_need_to_censor", "another_one", "there's_a_bunch", "i_won't_name_them_all"]

files = [r".\chromedriver.exe", r".\temp", r".\Logs"]

options = {
    'build_exe': {
        'packages': packages,
        'includes': includes,
        'include_files': files
    },
}

setup(
    name="Test",
    options=options,
    version="0.1",
    description='Testing Client',
    executables=executables
)

this is the script i compile the program with. the program is a tkinter-gui that calls a function that starts a test (that is given data from the ui via a json file).

i make the call with a button that calls a function start_click(notiz) within which the function gui_data_init from the module test_start is called

start_param = partial(start_click, notiz)
start_button = Button(buttonframe, text="Start", command=start_param)

def start_click(notiz):
    # data generation happens here and is stuffed into a json file

    thread = threading.Thread(target=test_start.gui_data_init, args=(jsonpath,))
    thread.start()

the (i think) relevant part of test_start:

def gui_data_init(jsonpath):
    form_data = testing_lib.form_input(jsonpath)
    logn = form_data[0]  # Login Name
    passw = form_data[1]  # Passwort
    # There are many more of those, can't be looped properly some have conditions

    testrun(list_of_input_data_for_the_test)

this function calls a function form input from a module testing_lib, where the data is imported from a the created json file and that hosts a plethora of functions that use selenium and many other things to further ease the writing of specific tests. the function testrun() is what calls many other functions from many other modules that actually execute the test depending on which paths have been chosen, etc.

As I said above, everything works absolutely perfect when i compile with base=None and there is a console running additionally to the UI. But when i compile with base="Win32GUI" in order to hide the window the button-click will execute the function start_click but the call "test_start.gui_data_init" inside will not be executed.

Why is that and how do i get rid of the console and still run the program properly? I have tried a lot of things but nothing i found so far has worked.


Solution

  • Apparently having a direct output to console (f.e. print()) will render the program non-functional if the console is removed. In this specific case it's the webdriver-manager that prints to console. I wasn't able to change this so this is just how it'll be.