Hitokiri
Hitokiri

Reputation: 13

Creation of Tkinter exe using nuitka opens and closes without feedback. App works perfectly when running in python environment

When I apply the main loop solution, I still have the same problem. The script works perfectly when running the .py script. So the exe is created with the nuitka, and when I run the exe the console opens for a few seconds, and then closes, but nothing happens. I also opened the exe using cmd, but it just completes without any output. Can someone try to create sample app and test this? Or maybe you already c the solution when looking at the code. You need a few pdf files and a XLS sheet in a folder called "Project Fluvius" on the user's desktop.

import os
import re
import pandas as pd
import PyPDF2
import getmac  # For MAC address check
import requests  # To fetch online time
from reportlab.lib.pagesizes import A4
from reportlab.pdfgen import canvas
from tkinter import Tk, simpledialog, messagebox
from datetime import datetime, timedelta
import sys  # Needed for sys.exit(1)
import traceback  # For logging errors

# Log file setup
log_file = open("error_log.txt", "w")
sys.stdout = log_file
sys.stderr = log_file

# Define paths and global variables
desktop_path = os.path.join(os.path.expanduser('~'), 'Desktop')
project_folder = os.path.join(desktop_path, 'Project XXXXXX')
pdf_folder_path = project_folder  # Assuming PDFs are in 'Project XXXXXX' folder
master_file_path = os.path.join(project_folder, 'lege meetstaat.1.xls')
output_pdf_path = os.path.join(project_folder, 'pdf_totals_output.pdf')
timestamp_file = os.path.join(project_folder, 'timestamp.txt')  # Store first run date here

TRIAL_PERIOD_DAYS = 90  # 90 days trial
AUTHORIZED_MAC_ADDRESS = "XX:XX:XX:XX:XX:XX"  # Update MAC address

# Functions
def get_mac_address():
    """Get MAC address of current machine."""
    mac_address = getmac.get_mac_address()
    print(f"Detected MAC Address: {mac_address}")
    return mac_address

def check_mac_address():
    """Ensure the current machine is authorized by MAC address."""
    print("MAC address check")
    mac_address = get_mac_address()
    if mac_address != AUTHORIZED_MAC_ADDRESS:
        print(f"Unauthorized device. Access denied. Current MAC Address: {mac_address}")
        messagebox.showerror("Unauthorized Access", "This device is not authorized to use this application.")
        sys.exit(1)

def get_online_time():
    """Fetch the current time from an online API."""
    try:
        print("Fetching online time")
        response = requests.get('http://worldtimeapi.org/api/ip')
        if response.status_code == 200:
            online_time = response.json()['datetime']
            print(f"Fetched online time: {online_time}")
            return datetime.strptime(online_time, "%Y-%m-%dT%H:%M:%S.%f%z").replace(tzinfo=None)
    except Exception as e:
        print(f"Error fetching online time: {e}")
        return None  # If online time is not available, return None

def store_first_run_date(first_run_date):
    """Store the first run date in a file."""
    with open(timestamp_file, 'w') as f:
        f.write(first_run_date.strftime('%Y-%m-%d'))
    print(f"First run date stored: {first_run_date.strftime('%Y-%m-%d')}")

def load_first_run_date():
    """Load the first run date from the file."""
    if os.path.exists(timestamp_file):
        with open(timestamp_file, 'r') as f:
            date_str = f.read().strip()
            print(f"First run date loaded: {date_str}")
            return datetime.strptime(date_str, '%Y-%m-%d')
    print("No first run date found.")
    return None

def check_trial_period():
    """Ensure the trial period has not expired."""
    print("Trial period check")
    first_run_date = load_first_run_date()
    current_time = get_online_time() or datetime.now()

    if first_run_date is None:
        first_run_date = current_time
        store_first_run_date(first_run_date)
    else:
        days_since_first_run = (current_time - first_run_date).days
        print(f"Days since first run: {days_since_first_run}")

        if days_since_first_run > TRIAL_PERIOD_DAYS:
            root = Tk()
            root.withdraw()
            messagebox.showinfo("Subscription Expired", "Your subscription has expired. Please extend your license.")
            sys.exit(1)

def try_remove_output_pdf():
    """Remove existing PDF if it exists."""
    print("Checking for existing PDF output")
    if os.path.exists(output_pdf_path):
        try:
            os.remove(output_pdf_path)
            print(f"Removed existing PDF output: {output_pdf_path}")
        except PermissionError:
            root = Tk()
            root.withdraw()
            messagebox.showerror("File In Use", f"Please close the file '{output_pdf_path}' and try again.")
            raise

def extract_text_from_pdf(pdf_path):
    """Extract text from a PDF file."""
    print(f"Extracting text from PDF: {pdf_path}")
    text = ""
    try:
        with open(pdf_path, 'rb') as pdf_file:
            reader = PyPDF2.PdfReader(pdf_file)
            for page in range(len(reader.pages)):
                text += reader.pages[page].extract_text()
    except Exception as e:
        print(f"Error reading {pdf_path}: {e}")
    return text

def find_codes_in_pdf_text(pdf_text):
    """Find relevant codes in the extracted PDF text."""
    return re.findall(r'\b3\d{6}\b|\b3\d{8}\b', pdf_text)

def calculate_total_from_codes(codes, master_data, coefficient):
    """Calculate the total price from the found codes."""
    print("Calculating total from codes")
    total = 0.0
    fixed_coefficient_codes = ['3003597', '3003869', '3003868']

    for code in codes:
        code = str(code.strip())
        if code in master_data['Code'].values:
            price = master_data.loc[master_data['Code'] == code, 'Price'].values[0]
            if code in fixed_coefficient_codes:
                total += price
            else:
                total += price * coefficient
    return total

def get_calculation_coefficient():
    """Get the coefficient from user input."""
    root = Tk()
    root.withdraw()
    coefficient = simpledialog.askfloat("Input", "Enter the Calculation Coefficient:")
    return coefficient if coefficient else 1  # Default to 1 if nothing is entered

def generate_pdf(pdf_totals, output_pdf_path):
    """Generate the output PDF."""
    print("Generating PDF output")
    c = canvas.Canvas(output_pdf_path, pagesize=A4)
    width, height = A4
    
    c.setFont("Helvetica-Bold", 16)
    c.drawCentredString(width / 2, height - 50, "Fluvius totaal meetstaat")
    c.line(width / 2 - 100, height - 60, width / 2 + 100, height - 60)
    c.setFont("Helvetica", 12)

    line_height = 15
    margin_left = 40
    margin_right = width - 40
    total_sum = 0.0
    y_position = height - 100

    for pdf_file, total in pdf_totals.items():
        pdf_title = os.path.splitext(pdf_file)[0]
        total_sum += total
        c.drawString(margin_left, y_position, pdf_title)
        c.drawRightString(margin_right, y_position, f"€{total:.2f}")
        y_position -= line_height

    c.setFont("Helvetica-Bold", 12)
    c.drawCentredString(width / 2, y_position - 20, f"Totaal van meetstaten: €{total_sum:.2f}")
    c.showPage()
    c.save()

# Main function to organize the code execution
def main():
    try:
        # Print statements for checking where the execution reaches
        print("Start of the script")
        
        # Load master data
        master_data = pd.read_excel(master_file_path, sheet_name='Grondw')
        master_data = master_data.iloc[:, [1, 25]]
        master_data.columns = ['Code', 'Price']
        master_data['Code'] = master_data['Code'].astype(str).str.replace(r'\.0$', '', regex=True).str.strip()

        check_mac_address()
        check_trial_period()
        try_remove_output_pdf()

        pdf_files = [f for f in os.listdir(pdf_folder_path) if f.endswith('.pdf') and f != os.path.basename(output_pdf_path)]
        pdf_totals = {}
        coefficient = get_calculation_coefficient()

        for pdf_file in pdf_files:
            pdf_path = os.path.join(pdf_folder_path, pdf_file)
            pdf_text = extract_text_from_pdf(pdf_path)
            codes = find_codes_in_pdf_text(pdf_text)
            total = calculate_total_from_codes(codes, master_data, coefficient)
            pdf_totals[pdf_file] = total

        generate_pdf(pdf_totals, output_pdf_path)
        print(f"PDF report generated: {output_pdf_path}")

    except Exception as e:
        traceback.print_exc(file=log_file)
        sys.exit(1)
    
    finally:
        log_file.close()

# Entry point of the script
if __name__ == "__main__":
    main()
    main_window.mainloop()

Upvotes: 0

Views: 120

Answers (0)

Related Questions