IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

Agir si un script Python s'arrête.


Sujet :

Python

  1. #1
    Membre éprouvé

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Par défaut Agir si un script Python s'arrête.
    Bonjour,
    je voulais savoir s'il était possible d'agir au moment où l'utilisateur ferme la console Python liée à un script.

  2. #2
    Membre émérite
    Avatar de Antoine_935
    Profil pro
    Développeur web/mobile
    Inscrit en
    Juillet 2006
    Messages
    883
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur web/mobile

    Informations forums :
    Inscription : Juillet 2006
    Messages : 883
    Par défaut
    Le module atexit est peut-être ce que tu cherches.

  3. #3
    Membre Expert Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Par défaut
    Bonsoir,

    La discussion n'est pas à mon niveau mais comme le sujet est sympa...

    atexit n'est qu'une solution lorsque le script se termine normalement (de même que trace_variable sous Tkinter et consorts).
    Dans le cadre d'un arrêt brusque (CTRL C, arrêt de python comme par un kill sous linux, etc...) je cherche encore. A mon niveau il ne me semble pas possible d'agir sur un code à partir de lui même.

    Une idée (sous linux mais le principe est là) :
    Toutefois si ce code lance un script indépendant en lui envoyant son pid en argv il est possible pour le script secondaire de vérifier si le script est actif/non actif mais pas terminé/non actif et terminé. Soit :


    Pour le script principal
    Lancement : Création du script secondaire et lui passe son pid en argv.
    Actif : traitement et pid actif.
    Planté : pas le temp de créer le fichier trace. pid n'existe plus et le fichier trace n'est pas créer.
    Fin du script : Création du fichier trace dans le temp.

    Pour le script secondaire
    Actif : le pid existe
    Non actif mais pas terminé : le pid n'existe plus mais le fichier trace de fin de script n'est pas crée. Relance du script et récup de son pid.
    Non actif et fini : le pid existe et le fichier trace aussi : je supprime le fichier trace et tout le monde quitte.


    Cela se complique si c'est pour un traitement, ce qui me semble est le cas. Dans ce cas la création d'un fichier avec le dernier élément traité ralenti énormément le code.

    Voili, une idée au passage...

    @+

  4. #4
    Membre émérite
    Avatar de Antoine_935
    Profil pro
    Développeur web/mobile
    Inscrit en
    Juillet 2006
    Messages
    883
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur web/mobile

    Informations forums :
    Inscription : Juillet 2006
    Messages : 883
    Par défaut
    Je ne savais pas que atexit ne gèrait pas les exceptions. A vrai dire, je ne me suis jamais penché sur ce module, mais mnt que tu le dis, ça me parait un comportement assez logique.

    Il reste la solution du try/finally.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    def main():
        # du code
     
    if __name__ == "__main__":
        try:
            main()
        finally:
            # Code de finalisation

  5. #5
    Membre Expert Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Par défaut
    Bonjour,

    Bien vu le finally. Sur un ctrl c cela fonctionne.
    Par contre cela ne prend pas en compte une fermeture du shell (demande de rambc) ou un arrêt externe du script (kill/arrêt du processus).

    Je parle dans le cadre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    def main():
        a = 0
        while a < 10000000000:
            a += 1
            print a
     
    if __name__ == "__main__":
        try:
            main()
        finally:
            open("/tmp/fichiertrace", "w").write('fin')
    Cela me semble un comportement normal. Dans le cadre d'un control c on demande l'arrêt du script et c'est intercepté. Les deux autres cas sont externes.

    Il ne reste donc plus que deux cas à gérer.

    Bonne journée.

  6. #6
    Membre Expert Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Par défaut
    Je sais que ma solution est moche mais pour en finir avec mon pseudo qbasic et en complément de ce que je disais.

    Le script principal écrit le script de contrôle dans le temporaire, le lance et le détruit en fin de traitement.
    Le script de contrôle fais le vérification de fin normale sur sa propre présence.
    Après tout se passe au niveau pid/argv.

    Voila pour ce qui est du retour vers l'archéologie informatique et dans l'attente de lire une solution plus 'pro'.

    @+

    Petit edit explicatif :
    Pour le script de contrôle
    Si le pid existe et que le script de contrôle existe : fonctionnement normal
    Si le pid n'existe plus et que le script de contrôle existe : il y a plantage > relance du script principal avec argv et arrêt du script de contrôle (puisque relancé par le principal)
    Si le pid n'existe plus et le script non plus : fin

    Le fait de faire un remove sur le script de contrôle n'empêche pas son fonctionnement.

    @

  7. #7
    Membre Expert Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Par défaut
    Dernières news : Ma solution ne fonctionne pas non plus. Le script de contrôle utilise le même shell donc à la fermeture de celui-ci c'est la cascade...

    @+

  8. #8
    Membre émérite
    Homme Profil pro
    Inscrit en
    Décembre 2007
    Messages
    758
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France

    Informations professionnelles :
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Décembre 2007
    Messages : 758
    Par défaut
    bonjour,

    il reste toujours nohup pour rendre le script insensible à la fermeture du terminal shell (mais pas insensible à l'arrêt de la machine ;p)

    sur Linux/Unix au moins je ne sais pas s'il y a l'équivalent sur Mac (probable) et sur win.

    http://en.wikipedia.org/wiki/Nohup

  9. #9
    Membre Expert
    Homme Profil pro
    Inscrit en
    Avril 2004
    Messages
    1 067
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 1 067
    Par défaut
    une solution serait de lancer le script dans une console fille, ça n'empêcherait pas la fermeture mais ça pourrait l'intercepter (en bash ou en python) :
    -on lance le script principale, genre : os.system('xterm -e "python mon_script"')
    -os.system pause jusqu'à la fermeture de la console xterm
    -traitement de la fermeture

  10. #10
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 699
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 699
    Par défaut
    CPython devrait interfacer tout les signaux unix et permettre de les traiter normalement. voir: http://www.python.org/doc/2.5.2/lib/module-signal.html
    Mais je n'ai peut être pas tout compris?

    atexit permet de déclarer les "callables" à exécuter lors d'une terminaison normale. Si la question est dans le cas ou la terminaison n'est pas normale...
    si de toutes façons, il faut terminer, il va falloir passer par tout les callables déclarés par atexit - ou refaire l'équivalent de atexit, dommage-.
    Donc, attraper le signal positionner un flag global disant 'sortie d'urgence' et sortir normalement pour passer par les atexit.
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  11. #11
    Membre Expert Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Par défaut
    Désolé wiztricks mais je n'arrive toujours pas à voir comment un code réagit à une intervention externe. Cela donne quoi en code ?

    Bonsoir rambc,

    Pas le temps ce soir mais voici un bout de code bidon (sans doute le pire) :

    principal.py :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    #!/usr/bin/env python
    # -*- coding: UTF8 -*-
    #
    #
    from sys import argv
    import os.path
    from signal import SIGQUIT
    from subprocess import Popen, PIPE
     
    def VerifArg():
        # Si il y a un argument c'est une relance
        try:
            if argv[1]:
                open('/tmp/fichiertrace', 'a').write('Relance de principal.py avec argument ' + argv[1] + os.linesep)
                return int(argv[1])
        except:
            # Nettoyage utilisation précédente
            if os.path.isfile('/tmp/fichiertrace'):
                os.remove('/tmp/fichiertrace')
            if os.path.isfile("/tmp/fichiercount"):
                os.remove('/tmp/fichiercount')
            # Creation du log
            open('/tmp/fichiertrace', 'w').write('Premier lancement de principal.py' + os.linesep)
            return 0
     
    def LanceControle():
        # Lancement de control.py
        LanceControle = 'python ' + os.path.join(os.getcwd(), 'controle.py ' + str(os.getpid()))
        controle = Popen(LanceControle, shell=True)
        sts = os.waitpid(controle.pid, 1)
        open('/tmp/fichiertrace', 'a').write('Pid de principal.py : ' + str(os.getpid()) + os.linesep)
        open('/tmp/fichiertrace', 'a').write('Pid de controle.py : ' + str(controle.pid) + os.linesep)
     
    Count = VerifArg()
    LanceControle()
    # Traitement pour l'exemple
    while Count < 1000000:
        Count += 1
        open('/tmp/fichiercount', 'w').write(str(Count))
    # Fin de traitement
    open('/tmp/fichiercount', 'w').write('fin')
    open('/tmp/fichiertrace', 'a').write('Fin du traitement dans principal.py' + os.linesep)
    # Possible d'os.remove de controle.py s'il est créer par le principal
    open('/tmp/fichiertrace', 'a').write('Fin de principal.py' + os.linesep)
    os._exit(0)
    controle.py :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    #!/usr/bin/env python
    # -*- coding: UTF8 -*-
    #
    #
    from sys import argv, stdout
    import os.path
    from time import sleep
    from subprocess import Popen, PIPE
     
    def Relance(count, MonPid):
        open('/tmp/fichiertrace', 'a').write("Erreur detectée : Relance de principal.py" + os.linesep + 'Avec pour argument count ' + str(count) + os.linesep)
        RelancePrincipal = 'python ' + os.path.join(os.getcwd(), 'principal.py ') + str(count)
        controle = Popen(RelancePrincipal, shell=True)
        sts = os.waitpid(controle.pid, 1)
        open('/tmp/fichiertrace', 'a').write('Fermeture de controle.py' + os.linesep)
        os._exit(0)
     
    open('/tmp/fichiertrace', 'a').write('Lancement de controle.py ' + os.linesep + 'Avec en argv le pid ' + str(argv[1]) + os.linesep)
    os.setsid()
    open('/tmp/fichiertrace', 'a').write('Changement de pid pour controle.py ' + '(' + str(os.getpid()) + ')' + os.linesep)
     
    attentefin = 'start'
    count = open('/tmp/fichiercount', 'r').read()
    while count != 'fin':
        Monps = Popen(['ps', '-e'], stdout=PIPE)
        Mongrep = Popen(['grep', str(argv[1])], stdin=Monps.stdout, stdout=PIPE)
        attentefin = Mongrep.communicate()[0]
        count = open('/tmp/fichiercount', 'r').read()
        if attentefin == '' and count != 'fin':
            Relance(count, os.getpid())
        # sleep(50)
     
    # Fin de controle.py
    open('/tmp/fichiertrace', 'a').write('Fermeture de controle.py' + os.linesep)
    os._exit(0)
    Et son log :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    patrice@Zeus:~/Bureau$ cat /tmp/fichiertrace
    Premier lancement de principal.py
    Pid de principal.py : 29475
    Pid de controle.py : 29476
    Lancement de controle.py 
    Avec en argv le pid 29475
    Changement de pid pour controle.py (29477)
    Erreur detectée : Relance de principal.py <----Fermeture de la fenêtre.
    Avec pour argument count 32577
    Relance de principal.py avec argument 32577
    Fermeture de controle.py
    Pid de principal.py : 29839
    Pid de controle.py : 29840
    Lancement de controle.py 
    Avec en argv le pid 29839
    Changement de pid pour controle.py (29841)
    Fin du traitement dans principal.py
    Fin de principal.py
    Fermeture de controle.py
    patrice@Zeus:~/Bureau$
    C'est plein de fautes mais cela semble fonctionner.
    Reste à rajouter le try d'Antoine_935 pour le ctrl + c.

    @+

  12. #12
    Membre éprouvé

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Par défaut
    Le post est allé au delà de ma question. Je reviendrais ici répondre plus tard car en ce moment je suis en plein passage de Python 26 à Python 3 et cela me pose quelques problèmes.

  13. #13
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 699
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 699
    Par défaut
    Citation Envoyé par PauseKawa Voir le message
    Désolé wiztricks mais je n'arrive toujours pas à voir comment un code réagit à une intervention externe. Cela donne quoi en code ?
    Et google?
    regardez à : http://www.doughellmann.com/PyMOTW/signal/index.html
    -W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  14. #14
    Membre Expert Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    Il est de notoriété que le novice.autodidacte utilise très mal ce moteur de recherche, surtout s'il n'a qu'une petite idée de ce qu'il recherche. Par contre avec un exemple c'est bien plus clair. Merci.
    Le couple threading/signal fonctionne très bien pour ce qui est d'agir en cas de fermeture de la fenêtre.

    Donc dans l'attente de savoir si c'est ce que recherche rambc.

    Ps: Je n'étais pas si loin dans l'idée. threading > script / interception par signal > interruption donc plus de pid. Il ne me manque plus qu'à écrire en python.

  15. #15
    Membre éprouvé

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Par défaut
    Citation Envoyé par PauseKawa Voir le message
    Donc dans l'attente de savoir si c'est ce que recherche rambc.
    Je vais tester cela en début de semaine. Je suis toujours dans mon passage de Python 2.6 à Python 3.1 .

    En tout cas, merci pour toutes ces contributions.

Discussions similaires

  1. Réponses: 7
    Dernier message: 18/04/2008, 20h07
  2. Réaliser un install pour un script python
    Par mcarluec dans le forum Déploiement/Installation
    Réponses: 13
    Dernier message: 15/04/2008, 08h14
  3. Accents Command Line depuis un script Python
    Par nicou50 dans le forum Général Python
    Réponses: 6
    Dernier message: 29/12/2006, 10h41
  4. Interpreter un script python dans un prog python
    Par romeo9423 dans le forum Général Python
    Réponses: 3
    Dernier message: 01/12/2005, 16h16
  5. Réponses: 3
    Dernier message: 05/04/2005, 14h26

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo