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 :

Redirigez stdout depuis une session telnet


Sujet :

Python

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Janvier 2010
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2010
    Messages : 66
    Points : 39
    Points
    39
    Par défaut Redirigez stdout depuis une session telnet
    Bonjour,

    Je débute en python et je cherche à redirigez la sortie standart d'une session Telnet vers la sortie standard (pour qu'elle soit utiliser par une IHM), j'ai essayé avec un fichier temporaire mais rien n'y fait, je n'arrive pas à avoir le résultat d'une commande exécuté sous ma session.

    Voici le code de ma classe Telnet qui en gros se connecte en Telnet à une carte électronique et envoies/reçois des commandes : (au passage j'utilise pexpect )

    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
    class ModTelnet(MXComm):
        def __init__(self):
            MXComm.__init__(self)
     
            self._tn = None
     
        def _connect(self):
            #connect to telnet session 
            try:
                self._tn = pexpect.spawn('telnet')
                i = self._tn.expect('telnet>', 3)
                if i == 0:
                    print 'connected'
                elif i !=0:
                    print 'connection error'
            except:
                print "Connection refused"
     
        def _receive(self):
            #receive data (= msg) from telnet stdout
            try:
                saveout = sys.stdout
                outfile = open('output.txt', 'w')
                sys.stdout = outfile
                outfile.flush()
                data = outfile.readline()
                outfile.close
                sys.stdout = saveout
                return data
            except:
                    print 'Connection error:'
                    raise Disconnected()
     
        def _send(self, command):
            #send command to telnet session
            try: 
     
                self._tn.send('help')
            except :
                    print 'Connection error:'
                    raise Disconnected()
    Merci d'avance pour votre aide !

  2. #2
    Membre actif
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2008
    Messages
    327
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2008
    Messages : 327
    Points : 257
    Points
    257
    Par défaut
    Bonjour,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    resultat = Popen('commande', stdout=PIPE).communicate()[0]

  3. #3
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Janvier 2010
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2010
    Messages : 66
    Points : 39
    Points
    39
    Par défaut
    Citation Envoyé par Apocalypses Voir le message
    Bonjour,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    resultat = Popen('commande', stdout=PIPE).communicate()[0]
    Oui mais comment peut-on faire sans utiliser de pipes ? j'aimerais utiliser pexpect pour simplifier le traitement du résultat de ma commande.

    Le but étant par la suite d'envoyer à un thread principale (MODiMX27) le résultat de la commande, je poste le code dans son ensemble:
    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
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    """
    Communication with embedded board
    """
     
    import pexpect
    import time
    import sys 
     
    import threading
    import Queue
    import subprocess
    import telnetlib
    from cStringIO import StringIO     
     
    class Dispatcher():     
        def __init__(self):
            self.msg_callbacks = {}  
     
        def register_callback(self, command, callback):
            if (command) not in self.msg_callbacks:
                self.msg_callbacks[command] = []
            self.msg_callbacks [command].append((callback))
     
        def unregister_callback(self, command, callback):
            self.msg_callbacks[command].remove((callback))     
     
    class Disconnected(BaseException):
        pass
     
    class Timeout(BaseException):
        pass
     
    class MXComm():
        def __init__(self):
            self.is_connected = False
            self._tn_to_gui = Queue.Queue()
            self._gui_to_tn = Queue.Queue()
            self._tx_item = None
     
        def _connect(self):
            pass
     
        def _receive(self):
            pass
     
        def _send(self, command):
            pass
     
        def connect(self):
            self._connect()
            self.is_connected = True
     
        def try_send_data(self):
            try:
                #get an item from the queue, try to send it
                #if the item wasn't sent, we don't get another one
                if self._tx_item is None:
                    self._tx_item = self._gui_to_tn.get_nowait()
                self._send(self._tx_item)
                self._tx_item = None #everything's ok, item sent
            except Queue.Empty:
                pass
            except Timeout:
                pass
            except Disconnected:
                self.is_connected = False
     
        #get data from telnet session to gui
        def try_get_data(self):
            try:
                rx_item = self._receive()
                self._tn_to_gui.put_nowait(rx_item)
            except Timeout:
                pass
            except Disconnected:
                self.is_connected = False
     
    #class ModOpenOCD(MXComm):
    #    def __init__(self):
    #        MXComm.__init__(self)
    #    
    #    def _connect(self):
    #        try:
    #            password = ""
    #            openocd = pexpect.spawn('sudo openocd -f %s' % (file))
    #            openocd.sendline(password)
    #        except:
    #            if'timeout error':
    #                print 'JTAG Connection error:'
    #                raise Disconnected() 
    #            else:
    #                raise Timeout()  
    #    #from the openocd session
    #    def _receive(self):
    #            #get the stop command
    #            data = raw_input() 
    #            return data
    #    #send to gui
    #    def _send(self, data):
    #            #send command line result 
    #            data = openocd.after
    #            return data
     
    class ModTelnet(MXComm):
        def __init__(self):
            MXComm.__init__(self)
     
            self._tn = None
     
        def _connect(self):
            #connect to telnet session @ localhost port 4444
            try:
                HOST = "localhost"
                port = "4444"
                #self._tn = telnetlib.Telnet(HOST, port)
                #tn.open(HOST, port)
                self._tn = pexpect.spawn('telnet')
                i = self._tn.expect('telnet>', 3)
                if i == 0:
                    print 'connected'
                elif i != 0 :
                    print 'connection error'
            except:
                print "Connection refused"
     
        def _receive(self):
            #receive data (= msg) from telnet stdout
            try:
                saveout = sys.stdout
                outfile = open('output.txt', 'w')
                sys.stdout = outfile
                outfile.flush()
                data = outfile.readline()
                outfile.close
                sys.stdout = saveout
                return data      
            except:
                    print 'Connection error:'
                    raise Disconnected()
     
        def _send(self, command):
            #send command to telnet session
            try: 
                self._tn.send('help')
            except :
                    print 'Connection error:'
                    raise Disconnected()
     
     
     
    class MODiMX27(threading.Thread):
        """
        Provides communication with a MDDiMX27 board
        It's using pexpect, openOCD and telnet to detect and communicate with the board.
        The class creates a thread with two queue to read/write data asynchronously.
        """
        def __init__(self, connection):
            threading.Thread.__init__(self)
     
            self._conn = connection
     
            self._dispatch = Dispatcher()
     
            self._is_running = True
            self.start()
     
        def __del__(self):
            self.stop()
            if self.isAlive():
                self.join()
     
        def stop(self):
            self._is_running = False
     
        def read_packet(self):
            try:
                return  self._get_packet()
            except Queue.Empty:
                return           
     
        def register_callbacks(self, callback_array):
            for command, callback in callback_array:
                self._dispatch.register_callback(command, callback)
     
        def unregister_callbacks(self, callback_array):
            for command, callback in callback_array:
                self._dispatch.unregister_callback(command, callback)
     
        def _get_packet(self):
            """ Get a message from telnet or the openOCD session (non blocking call), 
            raise queue empty if no message available """
            return self._conn._tn_to_gui.get_nowait() 
                    #self._conn.openocd_to_gui.get_nowait())
     
        def send_packet(self, command):
            """Send a message to the telnet or Openocd session (non-blocking call)"""
            self._conn._gui_to_tn.put_nowait(command)
     
        def is_connected(self):
            return self._conn.is_connected
     
        def run(self):
            """Thread main: read and write alternatively"""
            while self._is_running:
                    if not self._conn.is_connected:
                        try:
                            self._conn.connect()
                        except :
                            time.sleep(1.0)
     
                    else:
                        #-------- PC -> IMX -----
                        self._conn.try_send_data()
                        #-------- IMX -> PC -----
                        self._conn.try_get_data()  
     
    if __name__ =='__main__':
        try:
            tn = ModTelnet()
            #connect to telnet session
            board = MODiMX27(tn)
     
     
        except:
            print 'Cannot connect to MODiMX27!'
            exit(0)
    Pour résumer j'ai mon thread principale qui scrute les échanges entre une IHM et une session telnet (connecté à une carte).

  4. #4
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 281
    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 281
    Points : 36 768
    Points
    36 768
    Par défaut
    Salut,

    Il faut que vous précisiez comment est pris en charge le dialogue de bout en bout et que vous vous y teniez. Votre programme établit une connexion telnet 'à travers' ... peu importe et échange une suite de envoi commande, attente_réponse,...

    'envoi commande' est presque simple mais ""attendre réponse" l'est moins: quelles sont les conditions qui vous permettent de dire que... vous pourrez envoyer la commande suivante?

    pexpect aidant à parser les retours pour lever ces ambiguités => il est "bizarre" d'envoyer le flux de sortie "brut" à autre chose (sauf dans des états particuliers).

    Traduit avec un peu de code, la structure est de la forme suivante:
    note: mon exemple parle à un interpréteur Python, le dialogue est similaire à une session telnet...
    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
    import pexpect
    from pexpect import EOF, TIMEOUT
    from cStringIO import StringIO
     
    class Bidon(object):
        def __init__(self, logfile=None):
            c = self._c = pexpect.spawn ('/usr/bin/env python', logfile=logfile)
            self._wait_prompt()
     
        def _wait_prompt(self, timeout=None):
            c = self._c
            conditions = [ EOF, TIMEOUT, '>>>' ]
            index = c.expect(conditions, timeout=timeout)
            if index == 0:
                return 'eof', None
            elif index == 1:
                return 'timeout', None
            elif index == 2:
                return 'success', c.before.split('\r\n')[1:]
     
        def send_wait(self, cmd, timeout=None):
            c = self._c
            c.sendline(cmd)
            return self._wait_prompt(timeout)
     
    def test_bidon():
        logfile = StringIO()
        client = Bidon(logfile)
     
        cmd = 'a = 1'
        r = client.send_wait(cmd)
        if r:
            status, lines = r
            print "cmd: %s => %s, %s" % (cmd, status, ', '.join(lines))
            print logfile.getvalue()
     
        cmd = 'print a'
        r = client.send_wait(cmd)
        if r:
            status, lines = r
            print "cmd: %s => %s, %s" % (cmd, status, ', '.join(lines))
            print logfile.getvalue()
    Au passage, vous avez récupéré:
    - la sortie de la commande sous la forme d'une liste de "strings",
    - la sortie de Python dans un file-like,
    mais vous n'avez pas encore une interface asynchrone avec Bidon.

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

  5. #5
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Janvier 2010
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2010
    Messages : 66
    Points : 39
    Points
    39
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    Salut,

    Il faut que vous précisiez comment est pris en charge le dialogue de bout en bout et que vous vous y teniez. Votre programme établit une connexion telnet 'à travers' ... peu importe et échange une suite de envoi commande, attente_réponse,...

    'envoi commande' est presque simple mais ""attendre réponse" l'est moins: quelles sont les conditions qui vous permettent de dire que... vous pourrez envoyer la commande suivante?

    pexpect aidant à parser les retours pour lever ces ambiguités => il est "bizarre" d'envoyer le flux de sortie "brut" à autre chose (sauf dans des états particuliers).

    Traduit avec un peu de code, la structure est de la forme suivante:
    note: mon exemple parle à un interpréteur Python, le dialogue est similaire à une session telnet...
    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
    import pexpect
    from pexpect import EOF, TIMEOUT
     
    class Bidon(object):
        def __init__(self):
            c = self._c = pexpect.spawn ('/usr/bin/env python')
            c.expect ('>>>')
     
        def send_wait(self, cmd):
            conditions = [ '>>>']
            c = self._c
            c.sendline(cmd)
            index = c.expect(conditions)
            if index == 0:
                return c.before.split('\r\n')[1:]
     
     
    def test_bidon():
        client = Bidon()
     
        cmd = 'a = 1'
        r = client.send_wait(cmd)
        if r:
            print "cmd: %s => %s" % (cmd, ', '.join(r))
     
        cmd = 'print a'
        r = client.send_wait(cmd)
        if r:
            print "cmd: %s => %s" % (cmd, ', '.join(r))
    Au passage vous avez récupéré la sortie de la commande sous la forme d'une liste de "strings" mais vous n'avez pas encore une interface asynchrone avec Bidon.

    - W
    Les conditions autorisant l'envoi d'une commande sont pour moi à définir dans l'IHM avec la possibilité/impossibilité pour l'utilisateur d'effectuer tel ou tel action en fonction de la commande lancé.

    Pour le moment j'utilise le mécanisme de Queue pour synchroniser l'envoi et la réception de commandes/résultats.
    Les fonctions de callbacks me permettent de récupérer le résultat d'une commande. J'enregistre ma commande et une fonction de callbacks et j'attend un résultat en retour, enfin c'est ce que j'ai tenté de faire...

    Effectivement pour le coup j'utilise pexpect pour éventuellement repérer une erreur de connection.

    Merci pour l'exemple je vais tenter de le suivre !

Discussions similaires

  1. Comment s'initie une session telnet ?
    Par dva2tlse dans le forum Réseau
    Réponses: 76
    Dernier message: 11/09/2008, 18h52
  2. Récupérer les sessions connectées à mon application DEPUIS une session
    Par touria_lahsine dans le forum Développement Web en Java
    Réponses: 3
    Dernier message: 30/05/2008, 16h33
  3. Ouvrir une session telnet
    Par numostro dans le forum Administration
    Réponses: 2
    Dernier message: 29/12/2006, 10h12
  4. Initier une session telnet dans une session telnet
    Par benbs dans le forum Modules
    Réponses: 3
    Dernier message: 18/11/2006, 13h05
  5. Lancer une session telnet automatiquement
    Par Pragmateek dans le forum Windows
    Réponses: 2
    Dernier message: 23/05/2006, 16h37

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