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 :

Où trouver de l'info pour comprendre le threading avec Python ?


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé Avatar de calogerogigante
    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Avril 2003
    Messages
    602
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux

    Informations forums :
    Inscription : Avril 2003
    Messages : 602
    Par défaut Où trouver de l'info pour comprendre le threading avec Python ?
    Bonjour,

    Depuis septembre 2009 que je m'initie au superbe langage Python, je me dis qu'il est temps d'attaquer cette matière passionnante que sont les Threads, après avoir passé des semaines à faire connaissance avec les fondamentaux du langage et les widgets faciles à prendre en main de Tkinter.

    Je commence mes recherches sur le net (en anglais, français et italien) sur ce sujet, et là, patatraf : le contenu des moteurs de recherche contenant des tutoriels python ou des didacticiels complets sur le threading (basique ou avancé) me semble bien maigre ?

    Je ne suis nulle part avec ça...

    Quels conseils ou liens intéressants pourriez-vous donner à un débutant en Python pour entrer dans le monde des Threads ?
    Quel livre utiliser ? Quel site intéressant ? Quel petit script magique pour bien comprendre ?

    Merci d'avance pour vos avis...

  2. #2
    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,

    je m'étais un peu amusé avec ce script. il n'est pas de moi, et je ne me souviens pas où je l'ai trouvé sur la toile:

    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
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    #-*- coding:Utf-8 -*-
    import random
    from Queue import *
    from threading import Thread
    import time
     
    enStock = Queue(10)#notre pile, qui peut contenir 10 éléments max( 0 pour enlever la limite)
     
    class Magasin(Thread):
        """ Le 'producteur' : va remplir ses rayons de paquets de schtroumpfs """
        def __init__(self):
            self.ouvert = True
            Thread.__init__(self)
     
        def run(self):
            while self.ouvert :
     
                while not enStock.full() :
                    try :
     
                        enStock.put("ajout d'un paquet de schtroumpf",True,1000)
                        ### le Magasin va ajouter un paquet dans le rayon, et s'il y a plus de place,
                        ### va attendre pendant 1 seconde qu'un paquet soit acheté .
                    except Full,e :
                        print(" Il n'y a pas de place pour un paquet ! ");
     
                    else:
                        print(" On ajoute un paquet de schtroumpfs dans le rayon")
     
                time.sleep(10)
                #on attend 10 secondes avant que le magasin aille alimenter le rayon
     
    class Client(Thread):
        """ le consommateur, va prendre un/des paquet(s) de schtroumpf """
        def __init__(self,faim,numero):
            self.jAiFaim = faim
            self.numero = numero
            Thread.__init__(self)
        def run(self):
            while self.jAiFaim :
                time.sleep(1)
                #le client arrive au bout d'une seconde au rayon
     
                ok=False
                paquet = random.randint(1,4)
                #nombre de paquet qu'il va prendre
                i=1
                print(" Le client n° "+str(self.numero)+" veut "+str(paquet)+" paquet(s) de schtroumpfs")
                while i<=paquet :
                    try:
                        enStock.get(True,500)
                        ok = True
                        print(" n° "+ str(self.numero) + " : Prend un paquet")
     
                    except Empty, e:
                        ok = False
                        break
                    else:
                        i+=1
                if ok :
                    print(" Il reste " + str( enStock.qsize() ) +" paquet(s) de schtroumpfs")
                else :
                    print(" n° "+ str(self.numero) + " : Il n'y a pas assez de paquets")
                self.jAiFaim = False
     
    if __name__=='__main__':
        magasin = Magasin()
        magasin.ouvert = True
        print("##### Le magasin ouvre ses portes #####")
        magasin.start()
     
        i=1
        while i < 10:
            Client(faim = True ,numero = i).start()
            i=i+1
     
        time.sleep(60)
        magasin.ouvert=False
        print("##### Le magasin ferme ses portes #####")

  3. #3
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Pour sources d'inspiration.

    Je me suis un peu amusé avec les threads (module threading), et j'en ai fait quelques tutos.
    Ce n'est pas forcément une programmation géniale, mais ça respecte le manuel, c'est assez documenté et ça marche:

    http://python.jpvweb.com/mesrecettes...ion_par_thread

    J'ai aussi utilisé les threads pour faire une petite calculatrice de démo en script CGI sur un serveur Python local:

    http://python.jpvweb.com/mesrecettes...lculatrice_cgi

    J'ai enfin une plus grosse calculatrice graphique (tkinter) dont les calculs sont faits dans un thread, et dont le source est disponible:

    http://python.jpvweb.com/mesrecettespython/calculext

    Tyrtamos

  4. #4
    Membre éclairé Avatar de calogerogigante
    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Avril 2003
    Messages
    602
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux

    Informations forums :
    Inscription : Avril 2003
    Messages : 602
    Par défaut
    Merci Kango et Tyrtamos pour vos propositions de liens et de scripts fort intéressants...

    Je me lance alors, puisque j'ai deux personnes aimables qui ont l'air d'être calé dans le threading !


    J'aime bien voir quelquechose de concret (exemple un objet dans un canvas) qui symbolise l'activité du thread...

    Je me suis lancé dans un exemple multi-thread créé de mes petites mains, en étudiant vos exemples et la FAQ de Developpez.com.

    But : essayer d'en voir plusieurs en fonctionnement simultané. Voici ce que cela donne (attention, ça plante dans IDLE, je sais pas trop pourquoi ?) :

    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
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    #!/usr/local/bin/python
    # -*- coding:utf-8 -*-
    from Tkinter import *
    import threading
    import time
    from math import *
     
    class ObjetTournant(threading.Thread):
        def __init__(self, x, y, dans_canvas, ray, couleur):
            threading.Thread.__init__(self)
            self.rayon = ray
            self.x0 = x
            self.y0 = y
            self.coul = couleur
            self.angle = 0
            self.c = dans_canvas
            self.Terminated = False
            self.ref = self.c.create_line(self.x0,self.y0, self.x0+self.rayon, self.y0, width = 8, fill=self.coul)
     
        def run(self):
            self.angle = 0
            while not self.Terminated:
                new_x = self.x0 + self.rayon * sin (radians(self.angle))
                new_y = self.y0 + self.rayon * cos (radians(self.angle))
                self.c.coords(self.ref,self.x0,self.y0,new_x,new_y)
                self.angle += 1
                if self.angle > 360:
                    self.angle = 0
                time.sleep(0.01)
            print "Le thread ",self.coul," se termine proprement."
     
        def stop(self):
            self.Terminated = True
     
    class Application:
        def __init__(self):
            self.root=Tk()
            self.root.title('Objets tournant')
            self.root.geometry('600x400')
            self.root.protocol("WM_DELETE_WINDOW", self.finirapplication)
     
            self.c = Canvas(self.root, bg="white")
            self.c.pack(side=TOP, expand=YES, fill=BOTH)
     
            self.listeDesObjetsTournant = []
     
            self.listeDesObjetsTournant.append(ObjetTournant(100,200,self.c, 50, "red"))
            self.listeDesObjetsTournant.append(ObjetTournant(500,100,self.c, 30, "green"))
            self.listeDesObjetsTournant.append(ObjetTournant(340,200,self.c, 40, "blue"))
            self.listeDesObjetsTournant.append(ObjetTournant(200,100,self.c, 80, "black"))
            for obj in self.listeDesObjetsTournant:
                obj.start()
     
            self.root.mainloop()
     
        def finirapplication(self):
            for obj in self.listeDesObjetsTournant:
                obj.Terminated = True
                obj.stop()
            sys.exit()
     
    if __name__ == "__main__":
        app = Application()
    Je ne suis pas encore arrivé à trouver une solution pour placer des boutons de contrôle (démarrer, pause, arrêt) pour manipuler chaque objet tournant indépendamment.

    Mais j'ai quelques questions qui me turlupinent :

    - est-ce que ce code ci-dessus est correct ? (parce qu'il plante souvent mon IDLE, et même parfois l'exécutable python lui-même, carrément !)

    - quelle est la nature profonde de thread.start() : est-ce que cela veut dire qu'un thread ne démarre jamais QU'UNE SEULE FOIS ?

    - quelle est la nature de thread.stop() : est-ce que cela veut dire qu'un THREAD s'arrête définitivement ?

    Où mes deux dernières questions ne sont-elles que des choix qui doivent être fait par le développeur lui-même, en fonction des objectifs de ses threads ?

  5. #5
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Citation Envoyé par calogerogigante Voir le message
    est-ce que ce code ci-dessus est correct ? (parce qu'il plante souvent mon IDLE, et même parfois l'exécutable python lui-même, carrément !)
    Comme idle est écrit en python et tkinter, il y a quelquefois des pb, même avec des codes corrects. Pour savoir si le code est ok, il suffit de le lancer à partir d'une console, ou d'un autre outil de développement. Chez moi (j'utilise eclipse), ton code fonctionne.

    Citation Envoyé par calogerogigante Voir le message
    quelle est la nature profonde de thread.start() : est-ce que cela veut dire qu'un thread ne démarre jamais QU'UNE SEULE FOIS ?
    Le code de la méthode run est la seule partie qui s'exécute en tâche de fond. elle démarre par l'appel start() et se termine par la terminaison normale de la méthode run().

    Il n'y a pas de raison de lancer un thread déjà en exécution. Si on veut lancer plusieurs threads identiques, on ajoute des instances de la classe héritée de thread, et on les lance chacune séparément.

    Bien entendu, une fois qu'un thread est arrêté, on peut le relancer si c'est utile! On peut aussi le laisser en exécution et le faire travailler sur évènement.

    Citation Envoyé par calogerogigante Voir le message
    quelle est la nature de thread.stop() : est-ce que cela veut dire qu'un THREAD s'arrête définitivement ?
    Il y a aucun moyen fourni d'arrêter un thread. La solution que tu as utilisée est l'une des astuces connues. Elle conduit à arrêter sur demande la boucle dans run(), ce qui termine run(), et donc ce qui arrête le thread.

    Tyrtamos

  6. #6
    Membre éclairé Avatar de calogerogigante
    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Avril 2003
    Messages
    602
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux

    Informations forums :
    Inscription : Avril 2003
    Messages : 602
    Par défaut
    Merci pour ta réponse très complète, Tyrtamos...

    J'ai encore des soucis : je suis sous Windows Vista et Windows 7, j'ai des tas d'erreurs (parfois oui, parfois non) avec mon code suivant, qui ne fonctionne pas : je n'arrive pas à faire démarrer les Threads indépendamment les un des autres... Est-ce que les threads de Python ont des soucis avec Vista ou Seven ? Ou alors je les utilise mal ?

    Voici le code sur lequel j'ai avancé :

    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
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    #!/usr/local/bin/python
    # -*- coding:utf-8 -*-
    from Tkinter import *
    import threading
    import time
    from math import *
     
    class ObjetTournant(threading.Thread):
        def __init__(self, x, y, dans_canvas, ray, couleur):
            threading.Thread.__init__(self)
            self.rayon = ray
            self.x0 = x
            self.y0 = y
            self.coul = couleur
            self.angle = 0
            self.c = dans_canvas
            self.Fini = False
            self.ref = self.c.create_line(self.x0, self.y0, self.x0+self.rayon, self.y0, width = 8, fill=self.coul)
     
        def run(self):
            while not self.Fini:
                new_x = self.x0 + int(self.rayon * sin (radians(self.angle)))
                new_y = self.y0 + int(self.rayon * cos (radians(self.angle)))
                self.c.coords(self.ref, self.x0, self.y0, int(new_x), int(new_y))
                self.angle += 1
                if self.angle >= 360:
                    self.angle = 0
                time.sleep(0.01)
            print "Le thread ",self.coul," est fini."
     
        def stop(self):
            self.Fini = True
     
    class Application:
        def __init__(self):
            self.root=Tk()
            self.root.title('Objets tournants avec threads - v02')
            self.root.geometry('700x400')
            self.root.protocol("WM_DELETE_WINDOW", self.finirapplication)
     
            self.ca = Canvas(self.root, bg="white")
            self.ca.pack(side=LEFT, expand=YES, fill=BOTH)
     
            self.listeDesObjetsTournant = []
     
            self.listeDesObjetsTournant.append(ObjetTournant(100,200,self.ca, 50, "red"))
            self.listeDesObjetsTournant.append(ObjetTournant(500,100,self.ca, 30, "green"))
            self.listeDesObjetsTournant.append(ObjetTournant(340,200,self.ca, 40, "blue"))
            self.listeDesObjetsTournant.append(ObjetTournant(200,100,self.ca, 80, "black"))
     
            self.fra = Frame(self.root)
     
            t = 0
            for i in self.listeDesObjetsTournant:
                but1 = Button(self.fra, text="Start "+str(t), command=lambda m=i:self.objetdemarrer(m))
                but1.grid(row=t,column=0)
                but2 = Button(self.fra, text="Stop "+str(t), command=lambda m=i:self.objetstop(m))
                but2.grid(row=t,column=1)
                t += 1
     
            self.fra.pack(side=RIGHT)
     
            self.root.mainloop()
     
        def finirapplication(self):
            for obj in self.listeDesObjetsTournant:
                #obj.Fini = True
                obj.stop()
            sys.exit()
     
        def objetdemarrer(self, m):
            m.Fini = False
            m.start()
     
        def objetstop(self, m):
            m.stop()
     
    if __name__ == "__main__":
        app = Application()
    Message d'erreur fréquent :

    Exception in thread Thread-3:
    Traceback (most recent call last):
    File "C:\Python26\lib\threading.py", line 525, in __bootstrap_inner
    self.run()
    File "C:\PythonScripts\threads\objets_tournants_v02.py", line 24, in run
    self.c.coords(self.ref, self.x0, self.y0, int(new_x), int(new_y))
    File "C:\Python26\lib\lib-tk\Tkinter.py", line 2136, in coords
    self.tk.call((self._w, 'coords') + args)))
    ValueError: invalid literal for float(): None
    Comment arriver à faire quelquechose de beau et de propre, qui ne plante pas, pour visualiser concrètement mes threads par des objets tournants sur un canvas, que je puis démarrer et stopper à ma guise...

    Difficle, les threads... Difficile...

    EDIT : les problèmes de plantage de Tkinter et de ses threads semblent connus :
    http://mail.python.org/pipermail/pyt...ne/023465.html

  7. #7
    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
    Salut,

    Wiztricks, j'ai vu l'exemple que tu mets dans l'URL : ça a l'air super intéressant, mais je ne pige pas tout ce qui est dans ce code, malheureusement...
    Oui, je sais... vous ne venez pas d'un monde "geeks".

    Le soucis est qu'une programmation multi-threads plus sophistiquée que le modèle Workers où on fractionne le problème en plusieurs morceaux, mais on reste dans un modèle symétrique... demande une appropriation des paradigmes de programmation réseau - échanges de messages, asymétrie.

    Une bibliothèque graphique n'étant pas ré-entrante, l'utiliser dans un contexte multithreads signifie mettre en branle un modèle asymétrique et des échanges de messages. Beurk...

    Le seul langage de programmation ou l'écriture de ce genre de chose est "simple" est hélas l'assembleur... et Python.
    Pourquoi? Parce que çà a à voir avec la maîtrise du standard d'appel - vous savez la mécanique sous jacente aux appels de fonction qui sauvegardent et restorent le contexte de l'appelant.

    Pourquoi Python rend la vie aussi simple que l'assembleur dans ce cas, ben parce que le standard d'appel est callable(*args, **kwds) avec callable dans fonction ou méthode.... et que de là, le message devient le uplet (callable, *args, **kwds) autrement dit, une variable.

    Si mes neurones veulent bien bosser ce week end, j'essaierai de faire quelque chose de comestible...

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  8. #8
    Membre Expert
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Par défaut
    Je suis de plus en plus largué à chaque intervention des nouveaux intervenants !!
    Moi aussi !



    vous savez la mécanique sous jacente aux appels de fonction qui sauvegardent et restorent le contexte de l'appelant.
    Ben non, je ne sais pas.



    Si mes neurones veulent bien bosser ce week end, j'essaierai de faire quelque chose de comestible...
    Ce serait fort méritoire à vous, Grand Manitou, et satisfaisant pour nous, vu que cette file prolifère comme un champignon et pousse ses mycéliums dans divers concepts se cachant sous l’écorce......

  9. #9
    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 Standard d'appel == calling standard.
    En attendant, regardez ce que fait la fonction "processor" ci dessous.

    Code python : 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
    def processor(call, *args, **kwds):
        try:
            results = call(*args, **kwds)
        except:
            print "exception in call to %s" % call.__name__
            raise
        return results
     
    def decorator():
        def processed_callable(call):
            def wrapped_callable(*args, **kwds):
                result = processor(call, *args, **kwds)
                return result
            return wrapped_callable
        return processed_callable
     
    @decorator()
    def example(a, b, c):
        print a, b, c
        return True, a, b, c
     
    print example(1, 2, 3)

    example(1, 2, 3) est de la forme callable(*args, **kwds) avec

    • callable = example
    • *args = [ 1, 2, 3 ]
    • **kwds = None


    Le code transforme example(1, 2, 3) en uplet (example, [ 1, 2, 3 ], None).
    Et processor l'exécute...

    Grosso merdo, ce code est nul: il ne fait rien sinon ajouter de l'overhead autour d'"example" qui n'a rien demandé...
    Et cela à l'insu de l'appelant, magie du décorateur...

    Tout le truc va être de passer de:
    callable(*args, **kwds)
    devient: uplet: (callable, *args, **kwds)
    devient: message!!!
    qu'on acheminera et qu'on exécutera (méthode) dans le contexte de la cible.

    Faisons apparaître Message dans cette boue:

    Code python : 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
    class Message():
        def __init__(self, call, *args, **kwds):
            # pack
            self._prototype = (call, args, kwds)
     
        def invoke(self):
            # unpack
            method, args, kwds =  self._prototype
            try:
                results = method (*args, **kwds)
            except:
                print "exception in call to %s" % method.__name__
                raise
            return results        
     
    def processor(m):
        return  m.invoke()
     
    def decorator():
        def processed_callable(call):
            def wrapped_callable(*args, **kwds):
                m = Message(call, *args, **kwds)
                result = processor(m)
                return result
            return wrapped_callable
        return processed_callable
     
    @decorator()
    def example(a, b, c):
        print a, b, c
        return True, a, b, c
     
    print example(1, 2, 3)

    Notre poovre example n'a toujours rien vu...
    Cà se passe derrière la scène, dans l'univers étrange des meta.

    Jusqu'à présent nous avons construit sous "example" tout un échafaudage qui joue sur l'équivalence:
    callable(*args, **kwds) <=> uplet: (callable, *args, **kwds) <=> message

    Laissez reposer les neurones là dessus pendant 24heures.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  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 Digression sur l'orthogonalité.
    Salut,

    Il y a encore des choses à raconter sur:
    callable(*args, **kwds) <=> uplet: (callable, *args, **kwds)

    Sur Wikipedia, vous trouverez cette définition de l'orthogonalité:
    Le jeu d'instructions d'un ordinateur est dit orthogonal lorsque (presque) toutes les instructions peuvent s'appliquer à tous les types de données. Un jeu d'instruction orthogonal simplifie la tâche du compilateur puisqu'il y a moins de cas particuliers à traiter : les opérations peuvent être appliquées telles quelles à n'importe quel type de donnée. Un exemple typique est le VAX ou le PDP-10.
    Le uplet: (callable, *args, **kwds) permet "d'orthogonaliser" les traitements qu'on va pouvoir faire dessus.
    => nous pourrons traiter cela comme n'importe quelles variables...

    Sans descendre dans l'architecture des jeux d'instructions machine...
    Vous avez un avantage de l'orthogonalité dans UNIX/Linux qui se réduit à:
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    int main(int argc, char** argv, char** envp) { exit(0); }
    i.e. le point d'entrée de tout programme C (ou autres) qui permet de le lancer depuis la ligne de commande (shell) via
    Que ce soit un script Bash, un programme C ou autre... à partir du moment ou ce standard d'appel est respecté, nous pouvons "invoquer" programme ou script.

    Ce que doivent être le contenu de p1, p2, p3 est important mais c'est une autre histoire. L'API permet de réduire le nombre de cas particuliers à traiter pour appeler n'importe quel script ou programme...

    Notez aussi la similitude entre callable(*args, **kwds) et main(int argc, char** argv, char** envp).
    Dans les deux cas, les paramètres sont une d'arguments de position (p1, p2, p3,...) et un dictionnaire.

    Entrer un nom de fichier suivi de chaines de caractères séparées par des espaces voilà qui est minimaliste...
    Difficile de faire moins, est-il possible de mettre "plus" sans casser la généralité?
    C'est ce minimum qui fait généralité et... orthogonalité.

    En C, main(int argc, char** argv, char** envp) n'est que le prototype de la fonction main... (pour les autres débrouillez vous)
    En Python, callable(*args, **kwds) est le prototype de n'importe quel callable... (*)

    - W

    (*) Et qu'écrire en C la transformation callable(*args, **kwds) <=> (callable, *args, **kwds) est un exercice que je ne suis jamais arrivé à faire sans lire une documentation ou pomper du code déjà fait
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  11. #11
    Membre éclairé Avatar de calogerogigante
    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Avril 2003
    Messages
    602
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux

    Informations forums :
    Inscription : Avril 2003
    Messages : 602
    Par défaut
    Salut Wiztricks,

    Je te remercie de tant de prouesses dans tes explications, mais je t'avoue que je n'y comprends rien... Je ne vois pas le lien direct (ni indirect) avec les choses que tu décris, et mon petit soucis double :

    - comprendre le threading en général

    - ne pas me mordre les doigts de voir python se planter quand les threads fonctionnent au sein d'une bibliothèque graphique...

    A ce stade, je suis un peu dégouté d'apprendre que Thread et Tkinter ne font pas bon ménage, et les solutions qui me sont proposées sont hors de ma portée.

    Je crois que je vais pour l'instant laisser tomber définitivement l'étude des threads, et gérer les animations contrôlées à la façon de ce qui est décrit ici :

    http://www.developpez.net/forums/d85...de-classe-gui/

Discussions similaires

  1. [PHP 5.0] Mon sujet pour comprendre la POO avec PHP
    Par Le nettoyeur dans le forum Langage
    Réponses: 3
    Dernier message: 09/07/2014, 18h05
  2. Trouver infos pour une liste dans une base de donnees
    Par clairejp dans le forum Requêtes et SQL.
    Réponses: 1
    Dernier message: 29/07/2011, 18h26
  3. 5 minutes pour comprendre le développement avec Kinect
    Par Gordon Fowler dans le forum Débuter
    Réponses: 10
    Dernier message: 07/07/2011, 11h18
  4. [Info] Nouvel Ubuntu 11.04 avec Python 2.7.1
    Par tyrtamos dans le forum Général Python
    Réponses: 11
    Dernier message: 04/05/2011, 10h48
  5. cmt se connecté a oracle pour faire une requete avec python
    Par dipajero dans le forum Bibliothèques tierces
    Réponses: 6
    Dernier message: 28/12/2005, 20h22

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