PyQT6 - works ok on Pycharm, but crashes as standalone .exe file on Windows

Hi all,

Thanks for joining me, as a newbie developer, I’ve also bought the book Create GUI Applications with Python & Qt6 by Martin Fitzpatrick, which is awesome, but as a newbie I failed right at the beginning…

I have made an app in Pycharm using PyQT6 GUI

On Pycharm it works perfectly with no bugs, but when I run it on windows 10 as one file .exe component made by Pyinstaller, it works ok on easy operations but within two nested for loops and one while loop it crashes. The windows event protocol gives out some unreadable piece of information

  • Application: main.exe
  • Version: 0.0.0.0
  • Faulting module: Qt6Core.dll
  • Faulting module version: 6.5.1.0
  • Exception code: c0000409
  • Exception offset: 00000000000156d8
  • Process ID: 1604
  • Faulting application path: C:\Users\username\path\to\main.exe
  • Faulting module path: C:\Users\username\path\to\PyQt6\Qt6\bin\Qt6Core.dll
  • Event ID: 70668c18-85bb-XXXX-9a2-095a450f72a3

On Mac the app works fine but the app uses Pyautogui commands on third party components, which I do not have on Mac, So I didn’t check all functionality on Mac. But the App is primarily made for Windows, using that components……
What to do next?? Thanks for any piece of advice.

1 Like

Without some minimal code and list of package versions under the different environments, it’s going to be hard for people to assist you.

Hi Nmstoker,
thanks for your quick reply,

Certainly, there is no Qt6Core.dll in my computer, actually it seems to need a 4GByte large file download, which I don’t wanna use and how it’s possible, that Pycharm also doesn’t need the whole file too? PyQt6.QtCore was imported in (venv) terminal by Pip.

The Programm is crashing when it’s searching a location of a .png picture revealing on the screen via pyautogui. The mouse is going to move but it suddenly freezes. It seems the picture is invisible while running .exe file but everything is ok in Pycharm while running Python.

Here are the imports which I use in the main class:

from constants import FONT_SIZE, MINUTES, LABELS, DEFAULT_VALUES, COLUMN_NAMES
 # Default values for the columns

 # Column names for the DataFrame

import csv

import os
import platform
import subprocess
from PIL import Image
import pandas as pd
from PyQt6.QtWidgets import (
    QApplication,
    QWidget,
    QLabel,
    QLineEdit,
    QPushButton,
    QHBoxLayout,
    QGridLayout,
    QVBoxLayout,
    QMessageBox,
    QFileDialog,
    QComboBox,
    QDateTimeEdit,
    QSlider,
    QScrollArea,
    QFrame, )
from PyQt6.QtCore import Qt, QDateTime
from datetime import datetime, timedelta

# Check if the file exists
if not os.path.exists("data.csv"):
    # Create the file and write the column names
    with open("data.csv", 'w', newline='') as file:
        writer = csv.writer(file)
        writer.writerow(COLUMN_NAMES)
        
        # Write the default values as the first row
        writer.writerow(DEFAULT_VALUES)
    
    print("data.csv created successfully.")
else:
    print("data.csv already exists.")



import datetime_playground_final
from photos_to_delete_ok_mirror_rotate_0000 import PhotoBrowserWindow
from default_and_all_ok_settings import DefaultValuesSetting
from copy_rotate_and_mirror_to_a_file import CopyAndSave

from names_manager import create_names_file, read_names, write_names

import pyautogui_script_for_pc_kodak

Within my app there are aprox 5 classes there, the main class contains an event loop

if __name__ == "__main__":
    create_names_file()

    app = QApplication([])
    window = MainWindow()
    window.show()
    app.exec()

Inside the main window there are created gadgets like Qbuttons, QLineEdits, Labels, sliders etc.
The main goal of this class is to create data.csv file where the paths, general instructions what to do and creation dates are stored.
The result of a data.csv file is a bunch of lines which represents selection of concrete photos in a photo card.

Till now everything works fine, I can select photos from a specified date, range of time they were made, I can choose files and copy selected photos from the photo card into the chosen file etc.

The program runs perfectly also as .exe file till now.

The harder part comes next:

The last choice what a user can select is a pyautogui automation in cooperation with two separately running different programs. The main task is to automatically load the selected photos like a human does by clicking buttons on those third party programs. So the program has the data.csv file and from the main.py is calling pc_kodak_parsing() function in a different file called pyautogui_script_for_pc_kodak.

The program still runs perfectly and does the tasks as expected. The crash is coming around the line signed by “=============“ as I described in my previous comment. I know, there are lots of repetitions in my code, first, I wanna solve this bug, than the repetitions. Thanks for understanding.

What is interesting, the program runs perfectly in Pycharm IDE with no sign of bugs.

So the question is how can I debug the .exe file in windbg program to correct my Python file, if there is no bug any more, according to Pycharm?

Here’s my function, where the potential line of crash is signed by “# ==========“ line .

import pyautogui as pg
import pandas as pd
import PySimpleGUI as sg
import time
import platform
import pyperclip
import os



def win_mac_text_conversion(path):  # windows - mac / versus \ conversion

    # path = r"I:/DCIM/102CANON//IMG_9977.JPG"
    os = platform.system()

    if os == "Windows":
        new_path = path.replace('/', '\\')
        new_path = new_path.replace('//', '\\')
    else:
        new_path = path.replace('\\', '/')

    print(new_path)
    return new_path


df = pd.read_csv("data.csv")


def pc_kodak_parsing():
        
    print(pg.size())

    # Display a confirm alert window

    # moving mouse to a safe position of another window
    pg.moveTo(20, 800)
    pg.leftClick()
    pg.press("F11")
    pg.sleep(2)
    pict1 = "images/rotate180.png"
    pict2 = "images/rotate90.png"
    max_retries = 5

    for index, row in df.iterrows():
        path2 = row["path"]
        delay = 0.1
          # windows - mac / vesus \ conversion
        if row["to_delete"] == 1:
            continue
        elif row['mirrored'] == 1:
            # photos 
            #print(str(s1) + “mirror + 180° ")
            # reading of the photo
            #pg.sleep(1)
            pg.leftClick()
            pg.press("alt")
            pg.press("s")
            pg.press("b")
            # Set a delay between each character (adjust as needed)
            pg.sleep(0.15)
            time.sleep(delay)

            # Type the text character by character

            # reading of the photo
            ##path2 = row["path"]
            # Repeat the task multiple times
            for _ in range(max_retries):
                # windows - mac / vesus \ conversion
                characters = win_mac_text_conversion(path2)
                for _ in range(max_retries):
                    characters = win_mac_text_conversion(path2)
                    if characters:
                        break
                    else:
                        characters = win_mac_text_conversion(path2)
                
                # Copy the path to the clipboard
                pyperclip.copy(characters)
                pg.hotkey('alt', 'n')
                # Simulate keyboard shortcut for pasting (Ctrl+V on Windows)
                pg.hotkey('ctrl', 'v')

                # Wait for a short duration
                time.sleep(1)

                # Check if the path exists
                if os.path.exists(characters):
                    break  # Exit the loop if the path exists

                # If the path doesn't exist, repeat the task

            # Handle the case if the path still doesn't exist after retries
            if not os.path.exists(characters):
                print("Path does not exist after multiple retries.")

            pg.sleep(0.35)
            time.sleep(delay)
            pg.hotkey("alt", "o")  # loading the photo
            found = False
            while not found:
                image_location = pg.locateOnScreen(pict1) and pg.locateOnScreen(pict2)
                if image_location:
                    found = True
                else:
                    pg.sleep(0.5)
            # loading of the photo
            # mirroring
            button_location = pg.locateOnScreen('images\mirror.png')
            button_point = pg.center(button_location)
            pg.moveTo((button_point.x), (button_point.y))
	    # ===============================================
            pg.sleep(0.25)
            pg.leftClick()
            pg.sleep(0.25)
            # rotation
            button_location = pg.locateOnScreen('images\rotate180.png')
            button_point = pg.center(button_location)
            pg.moveTo((button_point.x), (button_point.y))
            pg.sleep(0.5)
            pg.leftClick()
            pg.sleep(1)
            # save the photo
            pg.hotkey("ctrl", "s")
            # pg.press("enter")
            # pg.sleep(1)
            pg.sleep(1)
            button_location = pg.locateOnScreen('images\extraoral.png')
            button_point = pg.center(button_location)
            pg.moveTo((button_point.x), (button_point.y))
            pg.sleep(0.5)
            pg.leftClick()
            pg.sleep(0.5)
            pg.press("enter")
            # delete the screen
            pg.hotkey("alt", "o")
            pg.press("s")
            pg.moveTo(20, 800)

        elif (row["rotation"]):
            # face and person photos rotated 270° and save as others
            ##print(str(s1) + “rotation 180° + 90° ")
            # reading the photo
            #pg.sleep(1)
            pg.leftClick()
            pg.press("alt")
            pg.press("s")
            pg.press("b")
            pg.sleep(0.15)
               # windows - mac / vesus \ conversion

            # Type the text character by character

            

            # loading the photo

            # Repeat the task multiple times
            for _ in range(max_retries):
                # windows - mac / vesus \ conversion
                characters = win_mac_text_conversion(path2)
                for _ in range(max_retries):
                    characters = win_mac_text_conversion(path2)
                    if characters:
                        break
                    else:
                        characters = win_mac_text_conversion(path2)
                # Copy the path to the clipboard
                pyperclip.copy(characters)
                pg.hotkey('alt', 'n')
                # Simulate keyboard shortcut for pasting (Ctrl+V on Windows)
                pg.hotkey('ctrl', 'v')

                # Wait for a short duration
                time.sleep(1)

                # Check if the path exists
                if os.path.exists(characters):
                    break  # Exit the loop if the path exists

                # If the path doesn't exist, repeat the task

            # Handle the case if the path still doesn't exist after retries
            if not os.path.exists(characters):
                print("Path does not exist after multiple retries.")

            pg.sleep(0.25)
            pg.hotkey("alt", "o")
            found = False
            while not found:
                image_location = pg.locateOnScreen(pict1) and pg.locateOnScreen(pict2)
                if image_location:
                    found = True
            # loading the photo
            # rotating
            button_location = pg.locateOnScreen('images\otocit90.png')
            button_point = pg.center(button_location)
            pg.moveTo((button_point.x), (button_point.y))
            pg.sleep(0.5)
            pg.leftClick()
            pg.sleep(1)
            # rotation
            pg.sleep(0.5)
            pg.leftClick()
            pg.sleep(1)

            pg.sleep(0.5)
            pg.leftClick()
            pg.sleep(1)
            # saving
            pg.hotkey("ctrl", "s")
            pg.sleep(1)

            pg.press("enter")
            # delete the screen
            pg.hotkey("alt", "o")
            pg.press("s")
            pg.moveTo(20, 800)
        else:
            ##print(s1)
            pg.sleep(1)
            pg.leftClick()
            pg.press("alt")
            pg.press("s")
            pg.press("b")
            pg.sleep(0.15)

               # windows - mac / vesus \ conversion
            # Type the text character by character

            
            # loading the photo

            # Repeat the task multiple times
            for _ in range(max_retries):
                
                # windows - mac / vesus \ conversion
                characters = win_mac_text_conversion(path2)
                for _ in range(max_retries):
                    characters = win_mac_text_conversion(path2)
                    if characters:
                        break
                    else:
                        characters = win_mac_text_conversion(path2)
                # Copy the path to the clipboard
                pyperclip.copy(characters)

                pg.hotkey('alt', 'n')
                # Simulate keyboard shortcut for pasting (Ctrl+V on Windows)
                pg.hotkey('ctrl', 'v')

                # Wait for a short duration
                time.sleep(1)

                # Check if the path exists
                if os.path.exists(characters):
                    break  # Exit the loop if the path exists

                # If the path doesn't exist, repeat the task

            # Handle the case if the path still doesn't exist after retries
            if not os.path.exists(characters):
                print("Path does not exist after multiple retries.")

            pg.sleep(0.25)
            pg.hotkey("alt", "o")
            found = False
            while not found:
                image_location = pg.locateOnScreen(pict1) and pg.locateOnScreen(pict2)
                if image_location:
                    found = True
            # opening the photo
            # save as others
            # pg.hotkey("ctrl", "s")
            # pg.press("enter")
            # pg.sleep(1)
            # save as extaoral
            pg.hotkey("ctrl", "s")
            pg.sleep(1.5)
            button_location = pg.locateOnScreen('images\extraoral.png')
            button_point = pg.center(button_location)
            pg.moveTo((button_point.x), (button_point.y))
            pg.sleep(1.5)
            pg.leftClick()
            pg.sleep(1)
            pg.sleep(0.5)
            pg.press("enter")
            # delete the screen
            pg.hotkey("alt", "o")
            pg.press("s")
            pg.moveTo(20, 800)

        # next cycle
        ## print(f2)


        # number JPG on the photo card
   

Thanks for any kind of help, Milan

I have the same problem as you :face_holding_back_tears:

Hello @Milan welcome to the forum!

Possibly a little late to be of help. But are you running that function in a separate thread? If you run long-running code it will block the event loop (so Qt can’t communicate with Windows). After a while Windows will assume the application has crashed & throw up the error window – although usually you can opt to let it keep running.

There are examples in the books of running functions in background threads, which should help you solve that problem.

As a general tip, if you’re trying to package an application it’s best not to do the one-file package at first. That’s because it makes it harder to debug what’s going wrong. If you package as a folder, you can open the folder in a command prompt & run the built code directly & see if it shows any error messages.