How to Fix a cxFreeze Python Error in Main Script

If you’ve ever tried packaging a Python project using cx_Freeze and suddenly faced this dreaded message:

Python error in main script
Runtime error

trust me, you’re not alone. When I first ran into it, I was scratching my head for hours. After digging in, I realized the error wasn’t in my main game logic it was in the way I set up cx_Freeze. Let me walk you through my exact mistake, the fix, and how I turned this into a small learning project.

The Code That Caused the Error

Here’s the original setup.py I wrote:

import sys
from cx_Freeze import setup, Executable

base = None

if sys.platform == "win32":
    base = "win32GUI"   # <-- I thought this was correct

setup(
    name="application",
    version="0.1",
    description="app",
    executables=[Executable("TICTACTOE.py", base=base)]
)

And here’s my main script (TICTACTOE.py), which is just a console-based Tic Tac Toe game:

import copy as c
import sys

def printBoard(arg):
    i = 0
    for v in arg.keys():
        i += 1
        if i % 3 == 0 and i < 9:
            print(arg[v], '\n- + - + -')
        elif i == 9:
            print(arg[v])
        else:
            print(arg[v], '', '|', end=' ')

def check(b, arg):
    def plagfn(b):
        global looper
        looper = False
        plag = input('Play again? y/n ')
        if plag == 'Y':
            theBoard = c.copy(newBoard)
        else:
            sys.exit()

    val = list(b.values())
    l = [''] * 9
    u = [''] * 9
    d = [''] * 9
    for i in [0, 3, 6]:
        l[i] = (val[i] == val[i+1] == val[i+2] == arg)
    for i in range(3):
        u[i] = (val[i] == val[i+3] == val[i+6] == arg)
    for i in [0, 2]:
        d[i] = (val[i] == val[4] == val[8-i] == arg)

    if ('' not in b.values()):
        print('Its draw !')
        plagfn(b)
    if (True in l) or (True in u) or (True in d):
        print(arg, 'is a winner !')
        plagfn(b)

while True:
    theBoard = {'TL': '', 'TM': '', 'TR': '',
                'ML': '', 'MM': '', 'MR': '',
                'LL': '', 'LM': '', 'LR': ''}
    sample = {k: k for k in theBoard.keys()}
    newBoard = c.copy(theBoard)
    print('The viable inputs are \n')
    printBoard(sample)
    print('\nStart')
    printBoard(theBoard)
    looper = True
    i = 0
    while looper:
        i += 1
        arg = 'O' if i % 2 == 0 else 'X'
        v = input('\nYour turn ' + str(arg) + '! \n')
        while v not in list(theBoard.keys()):
            print('The viable inputs are \n')
            printBoard(sample)
            v = input('\nYour turn ' + str(arg) + '! \n')
        while theBoard[v]:
            print('Already played.')
            v = input('Your turn ' + str(arg) + '! \n')
        theBoard[v] = arg
        printBoard(theBoard)
        check(theBoard, arg)

The Error Explain

The real problem was here:

if sys.platform == "win32":
    base = "win32GUI"

When I used "win32GUI", cx_Freeze built a windowed application, not a console one.

  • A GUI app has no console, which means functions like print() and input() simply don’t work.
  • My Tic Tac Toe game depends heavily on input().
  • Every time the code tried to read user input, it threw an EOFError, and cx_Freeze displayed it as “python error in main script … runtime error”.

In short: I told cx_Freeze to make a GUI app even though I only had a console app.

The Fix

The fix is very simple. I just needed to build my program as a console app, not a GUI app.

import sys
from cx_Freeze import setup, Executable

base = None
# Keep base=None for console programs.
# Only use "Win32GUI" for GUI frameworks like tkinter or PyQt.

setup(
    name="application",
    version="0.1",
    description="app",
    executables=[Executable("TICTACTOE.py", base=base)]  # Console build
)

After that, the .exe launched with a console window, and my game worked perfectly.

Adding More Practice Functionality

Since this was a learning project, I took the opportunity to add a couple of new features.

Score Tracking Across Games

Instead of exiting immediately when someone won, I added a scoreboard:

scores = {"X": 0, "O": 0, "Draw": 0}

Every time someone wins (or it’s a draw), I update the score and show the players their results so far.

Replay Without Restarting the Program

Originally, the game exited completely after a win or draw.
I modified the replay logic so players can decide whether to continue:

def plagfn(b, result):
    global looper
    looper = False
    scores[result] += 1
    print("Scoreboard:", scores)
    plag = input('Play again? y/n ')
    if plag.lower() == 'y':
        return True
    else:
        sys.exit()

Now the game feels more like a mini tournament rather than a single match.

Final Thought

This debugging journey reminded me of two simple but powerful lessons: always match your app type with the correct cx_Freeze base use base=None for console apps and base="Win32GUI" for GUI frameworks like tkinter or PyQt and don’t just stop at fixing errors. Bugs can be opportunities to grow; by adding score tracking and replay loops, I turned a frustrating runtime issue into a chance to improve my game and sharpen my Python skills.

Related blog posts