Si j'ai un exécutable python compilé en exe, comment puis-je vérifier s'il est déjà en cours d'exécution dans le gestionnaire de tâches et si oui, éviter d'exécuter une nouvelle instance de celui-ci?
import wmi if (c.Win32_Process(name="Script.exe")): sys.exit() else: #script.exe's code
Le code ci-dessus utilise le module wmi pour vérifier si le programme est déjà en cours d'exécution, puis arrête l'exécution de la nouvelle instance. Le problème avec cela est que le script ne s'exécutera jamais. Cela est dû au fait que lorsque script.exe est exécuté pour la première fois, il apparaît immédiatement dans le gestionnaire de tâches. Le module WMI le détecte et le ferme dès son ouverture. J'ai confirmé cela en renommant l'exécutable en Script2.exe, qui exécute le programme très bien.
Existe-t-il un moyen de vérifier correctement si un exe python est déjà en cours d'exécution?
3 Réponses :
Une méthode générale pour cela consiste à verrouiller les fichiers. Parfois aussi appelés fichiers pid .
Lorsque le processus démarre, il crée un fichier dans un emplacement prédéfini. Si le processus démarre et que le fichier existe, vous supposez que le processus est déjà en cours d'exécution. Une fois le processus terminé, il doit nettoyer son fichier de verrouillage.
for process in processes: if process.pid != os.getpid() and process.name == script_name: sys.exit(1)
Il y a une meilleure manipulation qui pourrait être faite, mais c'est l'idée de base.
Vous pouvez également écrire votre programme pour qu'il s'exécute en tant que service Windows (un démon).
Pas idéal, mais vous pouvez également améliorer votre solution en vérifiant le pid
actuel ET le nom du programme.
import os LOCK_FILE = "C:\\Path\\To\\myapplication.lock" if os.path.exists(LOCK_FILE): print(f"LOCK FILE {LOCK_FILE} already exits. Exiting") sys.exit(1) else: with open(LOCK_FILE, 'w') as f: f.write(f'{os.getpid()}') try: main() finally: try: os.remove(LOCK_FILE) except OSError: pass
Une partie de la raison pour laquelle ce n'est pas idéal est que le nom de l'exécutable n'est pas garanti (comme vous l'avez noté, le nom de fichier peut simplement être changé et cela se brise)
Cette solution est parfaite pour la plupart des scripts python. Cependant, mon script doit constamment s'exécuter en arrière-plan. Puisqu'il n'y a pas de véritable «fin» au processus, lorsque le fichier de verrouillage est supprimé, le processus continue. Cela lui permet d'être rappelé alors que la version précédente est toujours en cours d'exécution.
Cette solution fonctionne toujours dans ce cas. when the lock file is removed
Le fichier de verrouillage ne sera pas supprimé de lui-même. Le seul cas où il devrait être supprimé est lorsque le programme s'arrête. Si le programme ne s'arrête jamais ( main()
s'exécute indéfiniment), le fichier ne sera jamais supprimé. La clause finally:
serait pour des situations comme si le système s'arrête. Python essaiera de nettoyer le fichier avant que le système ne s'éteigne, de sorte que le processus puisse démarrer lorsque le processus est démarré après le redémarrage du système.
Je n'ai pas vraiment pensé à tout cela - cela fonctionne en fait!
Heureux que cela fonctionne pour vous. J'ai également ajouté quelques alternatives ainsi que des pistes de réflexion :-)
is_process_exists
renvoie True
si le processus existe, False
sinon:
import psutil def is_process_exists(process_name): return bool([p for p in psutil.process_iter() if psutil.Process(p.pid).name() == process_name])
Je pense que le problème dans ce cas est que le script lui-même essaie de vérifier si le processus est en cours d'exécution ... mais bien sûr, il sera toujours en cours d'exécution si le programme vérifie son propre nom :-)
Si le fichier ne se supprime pas lorsque le système s'arrête, vous pouvez essayer ceci:
Créez un dossier temporaire .txt n'importe où sur votre système, puis empêchez tout autre programme d'y accéder en faisant croire à python qu'il est "actuellement utilisé par un autre programme". Par exemple:
import threading import os pth = os.getcwd() + '\\text.txt' if os.path.exists(pth): try: os.remove(pth) except PermissionError: sys.exit() else: open(pth,"w+").close() f = open(pth,"w+") def loop(): while True: pass threading.Thread(target=loop).start()
Si une autre instance du programme est exécutée, vous obtiendrez une PermissionError et le programme se fermera.
Solution soignée. Notez simplement que cela ne fonctionne que sur Windows. Et même dans ce cas, il peut également se briser dans des circonstances étranges, par exemple si le fichier de verrouillage est stocké sur un partage réseau, aussi improbable que cela puisse être.