Nach auto-py-to-exe wird Programm nicht ausgeführt

Probleme bei der Installation?
Antworten
holger63
User
Beiträge: 3
Registriert: Samstag 27. Mai 2023, 18:25

Hallo,

ich habe in Manjaro Linux ein Hangman Spiel, main.py. Im selben Ordner,
in dem die Datei ist, befindet sich auch die words.txt sowie ein Ordner
mit Bildern.
Wenn ich nun auto-py-to-exe aufrufe und als script location das script auswähle,
dann one drectory, window based, das Icon file "icon.ico" im selben Ordner auswähle,
unter additional files "add files" die words.txt auswähle und unter "add folder" den
Bilderordner und dann "covert py to exe" klicke arbeitet es auch.

Der Code auf der Seite sieht so aus:

Code: Alles auswählen

pyinstaller --noconfirm --onedir --windowed --icon "/home/holger/hangman3/icon.ico" --add-data "/home/holger/hangman3/words.txt:." --add-data "/home/holger/hangman3/Steps Images:Steps Images/"  "/home/holger/hangman3/main.py"
Ich hab dann in output/main alles drin (?) nur wenn ich auf einem anderen Linuxrechner
das ja dort enthaltene Programm "main" ausführen will passiert genau gar nichts.
Hab ich ein Verständnisproblem? Es sollte doch so sein dass ich das dann
auf anderen Linuxrechnern "einfach so" ausführen kann oder mach ich da was falsch?

Gruß
Holger
__deets__
User
Beiträge: 14522
Registriert: Mittwoch 14. Oktober 2015, 14:29

Da du keinen Code zeigst, muss man raten. Aber ich vermute du lädst die Dateien mittels relativen Pfaden. Das klappt nur, wenn das Arbeitsverzeichnis passend ist. Stattdessen musst du die Datei Pfade relative zum Skript mit __file__ ermitteln, oder in der Dokumentation von pyinstaller lesen, wie man sowas machen soll.
holger63
User
Beiträge: 3
Registriert: Samstag 27. Mai 2023, 18:25

Danke für die Antwort, in auto-py-to-exe hat man doch extra eine GUI um die entsprechenden Scripte, Dateien etc zu laden(?)

Hier mein Code der main.py

Code: Alles auswählen

#!/usr/bin/env python3

from tkinter import *
import tkinter.messagebox as mb

from PIL import ImageTk, Image
from screeninfo import get_monitors
from random import choice
from os import system



# Basic Hangman function
def get_word():
    words = []

    with open('words.txt', 'r') as wordlist:
        for line in wordlist:
            words.append(line)

    chosen_word = choice(words)

    return chosen_word


def main_function(btn: Button):
    global image_lbl, li_word, correct_guesses, incorrect_guesses
    global step_1, step_2, step_3, step_4, step_5, step_6, step_7, step_8, step_9, step_10, step_11

    if btn['text'] in li_word:
        btn.config(bg='SpringGreen', fg='Black')
        indices = [indx for indx, val in enumerate(li_word) if val == btn['text']]
        for index in indices:
            exec(f'ltr_{index}["text"] = btn["text"]')
            correct_guesses += 1

    else:
        btn.config(bg='Red', fg='White')
        incorrect_guesses += 1
        exec(f'image_lbl.config(image=step_{incorrect_guesses})')

    btn.config(state='disabled')

    if correct_guesses == word_length:
        image_lbl.config(image=won_image)
        mb.showinfo('Geschafft!', 'Du hast gewonnen!\nDer Mann ist froh sich auf dich verlassen zu haben!\nGlückwunsch!')
        root.destroy()
        system('python main.py')

    if incorrect_guesses == 11:
        mb.showerror('Der Mann ist tot!', 'Er hat sich auf dich verlassen und du lässt ihn hängen!')
        root.destroy()
        system('python main.py')


# Command functions for the buttons at the top-right of the screen
def instructions():
    mb.showinfo('',
"""Das Spiel ist einfach:
Du hast 5 Versuche den Mann zu retten, bei 6 falsch geratenen Buchstaben ist der Mann nicht mehr zu retten. 
Bei weniger als 6 falschen Buchstaben ist der Mann gerettet und wird dir sehr dankbar sein.""")


def end_game():
    surety = mb.askyesno('', 'Bist du sicher dass du das Spiel verlassen willst? \nDer aktuelle Stand wird nicht gespeichert')

    if surety:
        root.destroy()


def reset():
    surety = mb.askyesno('', "Bist du sicher das Spiel neu zu starten?")

    if surety:
        root.destroy()
        system('python main.py')


# Variables
buttons_details = [["a", "A", 25, 800], ["b", "B", 125, 800], ["c", "C", 225, 800], ["d", "D", 325, 800],
                   ["e", "E", 425, 800], ["f", "F", 525, 800], ["g", "G", 625, 800], ['h', "H", 725, 800],
                   ['i', "I", 825, 800], ['j', "J", 925, 800], ['k', "K", 1025, 800], ['l', "L", 1125, 800],
                   ['m', "M", 1225, 800], ['n', "N", 25, 900], ['o', "O", 125, 900], ['p', "P", 225, 900],
                   ['q', "Q", 325, 900], ['r', "R", 425, 900], ['s', "S", 525, 900], ['t', "T", 625, 900],
                   ['u', "U", 725, 900], ['v', "V", 825, 900], ['w', "W", 925, 900], ['x', "X", 1025, 900],
                   ['y', "Y", 1125, 900], ['z', "Z", 1225, 900]]

word = get_word()
word_length = len(word)-1

correct_guesses = 0
incorrect_guesses = 0

li_word = [char.upper() for char in word]
# Getting the computer screen's dimensions
monitor = get_monitors()[0]

width = monitor.width - 100
height = monitor.height - 100

# Initializing the window
root = Tk()
root.title('Hangman')
root.geometry(f'{width}x{height}')
root.resizable(0, 0)
root.config(bg='White')
root.positionfrom('user')

# Title Label
Label(text='Simones Galgenmännchen', font=("Comic Sans MS", 32, 'bold'), bg='White').place(relx=0.35, y=0)

# Asking if the user wants to play
start_ques = mb.askyesno('Geschichte',
'''Der Mann — ja, das ist sein Name — wurde zu unrecht inhaftiert und steht kurz vor der Todesstrafe.
Du kannst ihn jedoch retten! Du kannst 5 Mal falsche Buchstaben raten um das Rätsel des gesuchten Wortes 
zu lösen und den Mann zu retten. Schaffst du es nicht wird das Urteil des Mannes vollstreckt. 

Möchtest du versuchen das Rätsel zu lösen?
\n''')

if not start_ques:
    root.destroy()
    exit()

# Creating all the steps images in PhotoImage format
step_0 = ImageTk.PhotoImage(Image.open('Steps Images/Step 0.png'))
step_1 = ImageTk.PhotoImage(Image.open('Steps Images/Step 1.png'))
step_2 = ImageTk.PhotoImage(Image.open('Steps Images/Step 2.png'))
step_3 = ImageTk.PhotoImage(Image.open('Steps Images/Step 3.png'))
step_4 = ImageTk.PhotoImage(Image.open('Steps Images/Step 4.png'))
step_5 = ImageTk.PhotoImage(Image.open('Steps Images/Step 5.png'))
step_6 = ImageTk.PhotoImage(Image.open('Steps Images/Step 6.png'))
step_7 = ImageTk.PhotoImage(Image.open('Steps Images/Step 7.png'))
step_8 = ImageTk.PhotoImage(Image.open('Steps Images/Step 8.png'))
step_9 = ImageTk.PhotoImage(Image.open('Steps Images/Step 9.png'))
step_10 = ImageTk.PhotoImage(Image.open('Steps Images/Step 10.png'))
step_11 = ImageTk.PhotoImage(Image.open('Steps Images/Step 11.png'))
won_image = ImageTk.PhotoImage(Image.open('Steps Images/Winner.png'))

image_lbl = Label(root, image=step_0, bg='White')
image_lbl.place(relx=0.15, rely=0.1)

# Placing the word on the window
Label(root, text='Zu erratenes Wort:', font=("Georgia", 30, 'bold'), bg='White').place(relx=0.635, rely=0.3)

x = 0.6
i = 0
while i < word_length:
    exec(f'''ltr_{i} = Label(root, text="_", bg="White", font=("Georgia", 50, 'bold')); ltr_{i}.place(relx={x}, rely=0.45)''')
    x += 0.04
    i += 1

# Creating all the letter buttons
for button in buttons_details:
    exec(f'''{button[0]}_btn = Button(root, text=button[1], width=9, height=3, bg="DeepSkyBlue", 
         command=lambda: main_function({button[0]}_btn))''')
    exec(f'{button[0]}_btn.place(x=button[2], y=button[3])')

Button(root, text='    Anleitung    ', font=("PlayfairDisplay", 12, 'bold'), bg='DeepSkyBlue',
       command=instructions).place(x=1125, y=100)

Button(root, text='Beenden', font=("PlayfairDisplay", 12, 'bold'), width=13, bg='DeepSkyBlue',
       command=end_game).place(x=1125, y=250)

Button(root, text='Neustart', font=("PlayfairDisplay", 12, 'bold'), width=13, bg='DeepSkyBlue',
       command=reset).place(x=1125, y=175)

# Finalizing the window
root.mainloop()
__deets__
User
Beiträge: 14522
Registriert: Mittwoch 14. Oktober 2015, 14:29

Es geht nicht um eine GUI. Es geht um sowas hier:

Code: Alles auswählen

Image.open('Steps Images/Step 0.png')
Das ist ein relativer Pfad. Image.open weiss nichts von pyinstaller oder sonstewas. Das benutzt die normalen Dateioperationen, um diese Datei zu oeffnen. Und weil die kein absoluter Pfad ist, muss die relativ zu *etwas* aufgeloest werden. Und *etwas* ist eben das Arbeitsverzeichnis.

Statt das also so zu machen, musst du rausfinden, wie man das mit pyinstaller macht. Wie schon erwaehnt, dazu hat der Dokumentation: https://pyinstaller.org/en/stable/runti ... ation.html
Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

*-Importe verwendet man nicht, weil man damit unkontrolliert Namen in den eigenen Namensraum schaufelt.
Bei Text-Dateien sollte man immer ein Encoding angeben, in dem die Daten interpretiert werden sollten. "words.txt" wird im aktuellen Arbeitsverzeichnis gesucht, da muß also auch Deine words.txt liegen.
Vergiss gleich wieder, dass es global überhaupt gibt. Für saubere GUI-Programme braucht man Klassen-Definitionen.
Wenn man ein Programm von vorne starten will, dann benutzt man eine Schleife, bzw. bei GUIs eine reset-Methode, die den Zustand zürcksetzt, und ruft nicht sich selbst per `os.system` auf.
`exec` benutzt man nicht, statt Variabelnnamen zusammenzustückeln verwendet man die passende Datenstruktur, also Listen.
GUI-Programme laufen nicht linear von oben nach unten ab, sondern sind ereignisgesteuert, die Frage nach dem start_gues sollte also in diesem Loop sein.
holger63
User
Beiträge: 3
Registriert: Samstag 27. Mai 2023, 18:25

Vielen Dank für die vielen Hinweise und Tipps!
Dann werde ich das mal neu machen und mich
erneut melden bei Problemen...

Viele Grüße
Holger
Antworten