Partage
  • Partager sur Facebook
  • Partager sur Twitter

Créer un exécutable PyQt (problème chemin listes)

    13 décembre 2023 à 20:57:46

    Bonjour !
    J'ai créé un script Quiz avec PyQt (Python3), celui-ci fonctionne parfaitement quand je l'execute dans le terminal.
    Le soucis c'est qu'après la création de l'exécutable, le script n'arrive plus à aller chercher les listes (dictionnaires) et crash à la sélection.
    Je bosse dans le digital, mais je ne suis pas du tout dev. Je pense avoir config en chemin relatif & absolu mais je ne suis pas sûr de moi.
    Voici ma commande pour créer l'exécutable :
    sudo pyinstaller --onefile --noconsole --add-data 'Users/xxx/liste:./liste script.py
    Je n'ai pourtant pas le dossier 'listes' dans le paquet après avoir généré l'exécutable. Et l'ajouter manuellement moi même ne change rien..
    voici le code (j'ai volontairement remplacé mon nom après /Users/ par xxxx) : 
    import os
    from datetime import datetime
    from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QLineEdit, QPushButton, QLabel, QComboBox, QDialog, QTextEdit, QCheckBox
    import sys
    import random
    from PyQt5 import QtCore, QtGui
    import difflib
    
    
    chemin_scripts = "/Users/XXX/Desktop/Script/"
    langues = {
    	"Anglais": {
    		"Fruits_Vegetables": "/Users/xxx/Desktop/Script/listes/Anglais/fruits_vegetables.txt",
    		"Supplies": "/Users/xxx/Desktop/Script/listes/Anglais/supplies.txt",
    		"Vehicles": "/Users/xxx/Desktop/Script/listes/Anglais/vehicles.txt",
    		"Weather": "/Users/xxx/Desktop/Script/listes/Anglais/weather.txt",
    		"Law": "/Users/xxx/Desktop/Script/listes/Anglais/law.txt",
    		"Bodypart": "/Users/xxx/Desktop/Script/listes/Anglais/bodypart.txt",
    		"World": "/Users/xxx/Desktop/Script/listes/Anglais/world.txt",
    		"Seaside": "/Users/xxx/Desktop/Script/listes/Anglais/seaside.txt",
    		"Time": "/Users/xxx/Desktop/Script/listes/Anglais/time.txt",
    		"Conjunctions_pronouns": "/Users/xxx/Desktop/Script/listes/Anglais/conjonctions_pronouns.txt",
    		"Adjectives": "/Users/xxx/Desktop/Script/listes/Anglais/adjectives.txt",
    		"Adverbs_prepositions": "/Users/xxxx/Desktop/Script/listes/Anglais/adverbs_prepositions.txt",
    		"Words": "/Users/xxxxx/Desktop/Script/listes/Anglais/words.txt",
    		"Nouns": "/Users/xxxxx/Desktop/Script/listes/Anglais/nouns.txt",
    		"Verbs": "/Users/xxxxx/Desktop/Script/listes/Anglais/verbs.txt",
    
    
    
    		# ... (autres thèmes anglais)
    	},
    	"Italien": {
    		# Thèmes italiens avec leur chemin
    	},
    	"Espagnol": {
    		# Thèmes espagnols avec leur chemin
    	},
    	"Algérien": {
    		# Thèmes espagnols avec leur chemin
    	},
    
    	# Ajoutez d'autres langues avec leurs thèmes ici
    }
    
    class Interface(QWidget):
    	def __init__(self):
    		super().__init__()
    		self.setWindowTitle("Languages trainer")
    		self.initUI()
    
    	def initUI(self):
    		layout = QVBoxLayout()
    		self.setWindowTitle("Languages trainer")
    
    		self.label_langue = QLabel("Choisissez une langue :")
    		layout.addWidget(self.label_langue)
    
    		self.combo_langues = QComboBox()
    		self.combo_langues.addItems(langues.keys())
    		layout.addWidget(self.combo_langues)
    
    		self.button_langue = QPushButton("Valider langue")
    		self.button_langue.clicked.connect(self.selectLangue)
    		layout.addWidget(self.button_langue)
    
    		self.label_theme = QLabel("")
    		layout.addWidget(self.label_theme)
    
    		layout.addSpacing(20)
    
    		self.label_select_theme = QLabel("Choisissez le thème :")
    		layout.addWidget(self.label_select_theme)
    
    		self.combo_themes = QComboBox()
    		layout.addWidget(self.combo_themes)
    
    		self.button_executer = QPushButton("Ouvrir le Quiz !")
    		self.button_executer.clicked.connect(self.ouvrirFenetreTraduction)
    		layout.addWidget(self.button_executer)
    
    		self.button_historique = QPushButton("Historique des résultats")
    		self.button_historique.clicked.connect(self.ouvrirHistorique)
    		layout.addWidget(self.button_historique)
    
    		# Ajout de la case à cocher pour inverser les traductions
    		self.checkbox_inverser = QCheckBox("Inverser les traductions")
    		layout.addWidget(self.checkbox_inverser)
    
    		# Créer une instance de la classe FenetreTraduction
    		self.fenetre_traduction = None
    
    		self.checkbox_inverser.stateChanged.connect(self.inverserTraductions)
    
    		self.setLayout(layout)
    		self.show()
    
    	def inverserTraductions(self, state):
    		if self.fenetre_traduction is not None:
    			self.fenetre_traduction.mettreAJourInversion(state)
    
    		# ... (le reste de votre code)
    
    	def ouvrirHistorique(self):
    		historique = HistoriqueResultats()
    		historique.exec_()
    
    	def selectLangue(self):
    		langue = self.combo_langues.currentText()
    		themes = langues[langue]
    		self.combo_themes.clear()
    		self.combo_themes.addItems(themes.keys())
    		self.label_theme.setText(f"Langue sélectionnée : {langue}")
    
    	def ouvrirFenetreTraduction(self):
    		langue = self.combo_langues.currentText()
    		theme = self.combo_themes.currentText()
    		if langue in langues and theme in langues[langue]:
    			script = langues[langue][theme]
    			chemin_script = os.path.join(chemin_scripts, script)
    			chemin_mots = f"/Users/xxxx/Desktop/Script/listes/{langue}/{theme}.txt"
    			#chemin_mots = os.path.join(os.getcwd(), "listes", langue, theme, ".txt")
    
    			# Récupérer l'état de l'inversion de la case à cocher
    			etat_inversion = self.checkbox_inverser.isChecked()
    
    			# Création de la fenêtre de traduction
    			fenetre_traduction = FenetreTraduction(chemin_script, theme, chemin_mots)
    
    			# Mettre à jour l'état d'inversion dans la fenêtre de traduction
    			fenetre_traduction.mettreAJourInversion(etat_inversion)
    
    			fenetre_traduction.exec_()
    
    class HistoriqueResultats(QDialog):
    	def __init__(self):
    		super().__init__()
    		self.setWindowTitle("Historique des résultats")
    		self.initUI()
    
    	def initUI(self):
    		layout = QVBoxLayout()
    		self.setLayout(layout)  # Définissez le layout pour le QDialog
    
    		# Affichage des logs dans la fenêtre de logs existante
    		log_text = QTextEdit()
    		log_text.setReadOnly(True)
    		log_content = self.lireLogs()  # Méthode pour lire les logs depuis le fichier
    		log_text.setText(log_content)
    
    		layout.addWidget(log_text)
    		self.setWindowTitle("Logs")
    
    	def lireLogs(self):
    		# Lecture du fichier log pour récupérer les informations
    		with open("log_file.txt", "r") as file:
    			log_content = file.readlines()
    			log_content.reverse()  # Inverser l'ordre des lignes
    			log_content = ''.join(log_content)  # Convertir la liste inversée en une chaîne de caractères
    			return log_content
    
    	def afficherLogs(self):
    		# Lecture du fichier log pour afficher les informations
    		with open("log_file.txt", "r") as file:
    			log_content = file.readlines()
    			log_content.reverse()  # Inverser l'ordre des lignes
    			log_content = ''.join(log_content)  # Convertir la liste inversée en une chaîne de caractères
    
    			# Affichage des logs dans la fenêtre de logs existante
    			log_text = QTextEdit()
    			log_text.setReadOnly(True)
    			log_text.setText(log_content)
    			layout = QVBoxLayout()
    			layout.addWidget(log_text)
    			self.setLayout(layout)
    			self.setWindowTitle("Logs")
    			self.exec_()
    
    	def inverserTraductions(self, state):
    			if state == QtCore.Qt.Checked:
    				self.inverser = True
    			else:
    				self.inverser = False
    
    class FenetreTraduction(QDialog):
    	def __init__(self, chemin_script, theme, chemin_mots):
    		super().__init__()
    		self.chemin_script = chemin_script
    		self.theme = theme
    		self.chemin_mots = chemin_mots
    		self.mots = self.lireMots(chemin_mots)
    		self.index_mot = 0
    		self.total_responses = 0
    		self.correct_responses = 0
    		self.inverser = False
    		self.initUI()
    		self.mot_a_traduire = self.prochainMot()
    		self.afficherMot()
    		self.start_time = datetime.now()
    		self.log_file = open("log_file.txt", "a")
    		self.log_file.write(f"Session started at {self.start_time.strftime('%d/%m/%Y %H:%M')}\n")
    
    	def inverserTraductions(self, state):
    		if state == QtCore.Qt.Checked:
    			self.inverser = True
    		else:
    			self.inverser = False
    		self.mot_a_traduire = self.prochainMot()  # Mettre à jour le mot à traduire
    		self.afficherMot()  # Mettre à jour l'affichage
    
    	def mettreAJourInversion(self, etat_inversion):
    		self.inverser = etat_inversion
    		self.mot_a_traduire = self.prochainMot()  # Mettre à jour le mot à traduire
    		self.afficherMot()  # Mettre à jour l'affichage
    
    	# Le reste de votre code pour FenetreTraduction..
    
    	def closeEvent(self, event):
    		end_time = datetime.now()
    		session_duration = end_time - self.start_time
    
    		# Calcul du taux de winrate
    		win_rate = (self.correct_responses / self.total_responses) * 100 if self.total_responses != 0 else 0
    
    		# Formatage de la durée en heures et minutes uniquement
    		hours, remainder = divmod(session_duration.total_seconds(), 3600)
    		minutes, _ = divmod(remainder, 60)
    		duration_str = f"{int(hours):02}:{int(minutes):02}"
    
    		# Écriture des informations dans le fichier log à la fin de la session
    		log_info = f"Session started at {self.start_time.strftime('%d/%m/%Y %H:%M')}. Duration: {duration_str}. Responses: {self.total_responses}. Winrate: {win_rate:.2f}%\n"
    
    		with open("log_file.txt", "a") as file:
    			file.write(log_info)
    
    		# Appel de la méthode parent pour fermer la fenêtre
    		super().closeEvent(event)
    
    	def initUI(self):
    		self.setWindowTitle(f"Traduction pour le thème '{self.theme}'")
    		layout = QVBoxLayout()
    
    		self.label_mot = QLabel("Mot à traduire :")
    		layout.addWidget(self.label_mot)
    
    		# Création d'un widget contenant la QTextEdit pour le centrage
    		text_widget = QWidget()
    		text_layout = QVBoxLayout()
    		self.text_affichage_mot = QTextEdit()
    		self.text_affichage_mot.setFixedHeight(50)  # Ajuste la hauteur ici, par exemple à 50 pixels
    
    		# Set font size for the QTextEdit widget
    		self.text_affichage_mot.setFontPointSize(25)  # Change the size (e.g., 14)
    
    		self.text_affichage_mot.setReadOnly(True)
    		self.text_affichage_mot.setAlignment(QtCore.Qt.AlignCenter)  # Centre le texte horizontalement
    		text_layout.addWidget(self.text_affichage_mot)
    		text_widget.setLayout(text_layout)
    
    		layout.addWidget(text_widget)
    
    		self.label_resultat = QLabel()
    		self.label_resultat.setAlignment(QtCore.Qt.AlignCenter)
    		layout.addWidget(self.label_resultat)
    
    		self.label_traduction = QLabel("Traduction :")
    		layout.addWidget(self.label_traduction)
    
    		self.text_traduction = QLineEdit()
    		self.text_traduction.setFont(QtGui.QFont("Arial", 25))  # Change the font size to 20
    		layout.addWidget(self.text_traduction)
    
    		self.button_executer = QPushButton("Valider")
    		self.button_executer.clicked.connect(self.executerScript)
    		layout.addWidget(self.button_executer)
    
    		self.label_responses = QLabel("Réponses réalisées : 0")
    		self.label_responses.setFont(QtGui.QFont("Arial", 15))  # Change the font size to 20
    		layout.addWidget(self.label_responses)
    
    		self.label_winrate = QLabel("Taux de réussite : 0.00%")
    		self.label_winrate.setFont(QtGui.QFont("Arial", 15))  # Change the font size to 20
    		layout.addWidget(self.label_winrate)
    
    		layout.insertWidget(2, self.label_resultat)
    		self.setLayout(layout)
    
    	def lireMots(self, chemin_mots):
    		with open(chemin_mots, 'r') as file:
    			mots = {}
    			for line in file:
    				parts = line.strip().split(':')
    				if len(parts) == 2:
    					mot = parts[0].strip().strip('"')
    					traduction = parts[1].strip().strip('",')
    					mots[mot] = traduction
    
    			print("Mots récupérés du fichier :", mots)
    			return mots
    
    	def afficherMot(self):
    		if self.mot_a_traduire is not None:
    			if not self.inverser:
    				self.text_affichage_mot.setPlainText(self.mot_a_traduire)
    				if self.mot_a_traduire in self.mots:
    					self.text_traduction.setPlaceholderText("Entrez la traduction...")
    			else:
    				mots_a_traduire_fr = list(self.mots.values())
    				if mots_a_traduire_fr:
    					mot_a_traduire_fr = random.choice(mots_a_traduire_fr)
    					self.text_affichage_mot.setPlainText(mot_a_traduire_fr)
    					self.text_traduction.setPlaceholderText("Entrez la traduction...")
    
    
    	def prochainMot(self):
    						if self.mots:
    							mot_a_traduire = random.choice(list(self.mots.keys()))
    							return mot_a_traduire
    						return None
    
    	def executerScript(self):
    		traduction = self.text_traduction.text().strip().lower()
    		resultat = ""
    
    		if traduction:
    			mot_a_verifier = self.text_affichage_mot.toPlainText().strip()
    
    			if not self.inverser:
    				traduction_en_to_fr = self.mots.get(mot_a_verifier.lower())
    
    				# Vérification dans le sens normal (Anglais vers Français)
    				if traduction_en_to_fr and traduction.lower() == traduction_en_to_fr.lower():
    					resultat = "<span style='color:#2ecc71'>Bonne réponse!</span>"
    					self.correct_responses += 1
    				else:
    					resultat = "<span style='color:#e74c3c'>Mauvaise réponse!</span>"
    					if traduction_en_to_fr:
    						resultat += f" La bonne traduction est : {traduction_en_to_fr}"
    
    				self.total_responses += 1
    			else:
    				# Vérification dans le sens inverse (Français vers Anglais)
    				mot_francais_affiche = self.text_affichage_mot.toPlainText().strip().lower()
    				mot_traduit_attendu = None
    
    				# Chercher la traduction anglaise attendue pour ce mot français
    				for  mot1, mot2 in self.mots.items():
    					if mot2.lower() == mot_francais_affiche:
    						mot_traduit_attendu = mot1
    						break
    				#print(traduction)
    				#print(mot_traduit_attendu)
    				if mot_traduit_attendu and traduction.lower() == mot_traduit_attendu.lower():
    					resultat = "<span style='color:#2ecc71'>Bonne réponse!</span>"
    					self.correct_responses += 1
    				else:
    					resultat = "<span style='color:#e74c3c'>Mauvaise réponse!</span>"
    					if mot_traduit_attendu:
    						resultat += f" La bonne traduction est : {mot_traduit_attendu.capitalize()}"
    
    				self.total_responses += 1
    		# Reste du code
    
    		# Mettre à jour l'affichage des résultats et du taux de réussite
    		self.label_resultat.setText(resultat)
    		self.label_resultat.setStyleSheet("QLabel { margin-top: 10px; }")
    
    		self.label_responses.setText(f"Réponses réalisées : {self.total_responses}")
    		win_rate = (self.correct_responses / self.total_responses) * 100 if self.total_responses != 0 else 0
    
    		# Déterminez la couleur en fonction du taux de réussite
    		color = ""
    		if win_rate < 50:
    			color = "#e74c3c"  # Rouge
    		elif 50 <= win_rate < 75:
    			color = "#f1c40f"  # Jaune
    		else:
    			color = "#2ecc71"  # Vert
    
    		# Utilisez la couleur pour formater le texte du taux de réussite
    		winrate_text = f"Taux de réussite : <span style='color:{color}'>{win_rate:.2f}%</span>"
    		self.label_winrate.setText(winrate_text)
    
    		self.text_traduction.clear()
    
    		self.mot_a_traduire = self.prochainMot()
    		self.afficherMot()
    
    		self.index_mot += 1
    
    		# Mettre à jour l'affichage des résultats et du taux de réussite
    		self.label_resultat.setText(resultat)
    		self.label_resultat.setStyleSheet("QLabel { margin-top: 10px; }")
    
    		self.label_responses.setText(f"Réponses réalisées : {self.total_responses}")
    		win_rate = (self.correct_responses / self.total_responses) * 100 if self.total_responses != 0 else 0
    
    		# Déterminez la couleur en fonction du taux de réussite
    		color = ""
    		if win_rate < 50:
    			color = "#e74c3c"  # Rouge
    		elif 50 <= win_rate < 75:
    			color = "#f1c40f"  # Jaune
    		else:
    			color = "#2ecc71"  # Vert
    
    		# Utilisez la couleur pour formater le texte du taux de réussite
    		winrate_text = f"Taux de réussite : <span style='color:{color}'>{win_rate:.2f}%</span>"
    		self.label_winrate.setText(winrate_text)
    
    		self.text_traduction.clear()
    
    		self.mot_a_traduire = self.prochainMot()
    		self.afficherMot()
    
    		self.index_mot += 1
    
    if __name__ == "__main__":
    	app = QApplication(sys.argv)
    	interface = Interface()
    	sys.exit(app.exec_())
    
    Merci par avance pour votre aide 

    -
    Edité par RymaBr 13 décembre 2023 à 21:02:07

    • Partager sur Facebook
    • Partager sur Twitter
      14 décembre 2023 à 8:00:03

      Bonjour,

      Tu peux utiliser abspath du module os pour utiliser les chemins absolus. Je te laisse chercher sur la Doc officielle...

      • Partager sur Facebook
      • Partager sur Twitter

      Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
      La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

        14 décembre 2023 à 15:30:01

        Les noms de chemins qui commencent par / sont absolus. L'exécutable devrait donc les trouver.

        Normalement, fabriquer un petit script qui ouvre un de ces fichiers puis le packager avec pyinstaller pour vérifier qu'il le trouve toujours devrait vous permettre de mieux cerner le problème que vous avez (et de fournir des informations qui permette un diagnostic plutôt que des idées préconçues et invérifiables).

        • Partager sur Facebook
        • Partager sur Twitter

        Créer un exécutable PyQt (problème chemin listes)

        × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
        • Editeur
        • Markdown