Python et les interfaces consoles ********************************* Il est tout a fait possible en plus de la gestion d'argument (via ficher conf ou passage par la ligne de commande) de créer des interfaces consoles toutes à fait utilisables. On peut interagir avec un terminal de plusieurs façons mais si il n'est pas possible sans ncurse d'avoir une interface du type *vim* le grand avantage de ces interfaces sont: * rapidité de développement * utilisation de peu de ressource machine Utilisation basique ------------------- la fonction raw_input permet en mode console l'attente d'une information utilisateur .. code-block:: python mydata = raw_input('Prompt :') print (mydata) :: C:\Users\fraoustin\Desktop>python test3.py Prompt :coucou coucou Création d'un interpréteur -------------------------- Il faut pour cela utiliser le module cmd.Cmd .. code-block:: python import cmd, sys class HelloWorld(cmd.Cmd): """Simple command processor example.""" prompt = '>>>' def preloop(self): print 'preloop()' def postloop(self): print 'postloop()' def do_greet(self, person): if person: print "hi,", person else: print 'hi' def help_greet(self): print '\n'.join([ 'greet [person]', 'Greet the named person', ]) def do_test(self, line): print 'test' def default(self, line): print 'default(%s)' % line return cmd.Cmd.default(self, line) def do_exit(self, arg): """quit console""" sys.exit(1) if __name__ == '__main__': HelloWorld().cmdloop() :: C:\Users\fraoustin\Desktop>python test2.py preloop() >>>test test >>>greet tutu hi, tutu >>>help Documented commands (type help ): ======================================== exit greet help Undocumented commands: ====================== test >>>exit Il est possible de modifier à volonté le comportement de l'interpreteur Il est aussi possible de rajouter de la couleur dans le terminal en utilisant colorconsole http://code.google.com/p/colorconsole Création d'interface évoluée ---------------------------- Pour cela il faut utiliser le module colorconsole http://code.google.com/p/colorconsole qui donne accès à de nombreux paramètres du terminal le code suivant présente simplement l'affichage de l'heure de façon aléatoire sur l'ensemble du terminal avec un changement de couleur lui aussi aléatoire .. code-block:: python import colorconsole, colorconsole.terminal import sys import datetime import time import random list_color = colorconsole.terminal.colors.keys() term = colorconsole.terminal.get_terminal() term.set_title('test') columns = term._Terminal__get_console_info().dwMaximumWindowSize.X lines = term._Terminal__get_console_info().dwMaximumWindowSize.Y term.clear() term.reset() try: while(True): now = datetime.datetime.now() x = random.randint(1,columns-20) y = random.randint(1,lines) fgcolorrandom = list_color[int(random.random() * len(list_color))] term.set_color(fg=colorconsole.terminal.colors[fgcolorrandom], bk=colorconsole.terminal.colors["BLACK"]) term.print_at(x,y,now.strftime("%d/%m/%Y %H:%M:%S")) term.set_color(fg=colorconsole.terminal.colors["WHITE"], bk=colorconsole.terminal.colors["BLACK"]) time.sleep(1) term.clear() term.reset() except KeyboardInterrupt: pass term.clear() term.reset() term.restore_buffered_mode() Il est possible d'utiliser les fonctions raw_input pour avoir plus d'interaction ... mais cela impose d'arrêter le programme en cours .. code-block:: python import colorconsole, colorconsole.terminal import sys import datetime import time import random def randomColor(): return list_color[int(random.random() * len(list_color))] list_color = colorconsole.terminal.colors.keys() term = colorconsole.terminal.get_terminal() term.set_title('test') columns = term._Terminal__get_console_info().srWindow.Right - term._Terminal__get_console_info().srWindow.Left +1 lines = term._Terminal__get_console_info().srWindow.Bottom - term._Terminal__get_console_info().srWindow.Top +1 fgcolorrandom = randomColor() term.clear() term.reset() try: while(True): now = datetime.datetime.now() x = random.randint(1,columns-20) y = random.randint(1,lines) term.set_color(fg=colorconsole.terminal.colors[fgcolorrandom], bk=colorconsole.terminal.colors["BLACK"]) term.print_at(x,y,now.strftime("%d/%m/%Y %H:%M:%S")) term.set_color(fg=colorconsole.terminal.colors["WHITE"], bk=colorconsole.terminal.colors["BLACK"]) time.sleep(1) term.print_at(0,lines,'') if raw_input('changer de couleur') == 'c': fgcolorrandom = randomColor() term.clear() term.reset() except KeyboardInterrupt: pass term.clear() term.reset() term.restore_buffered_mode() il est possible de créer un listener qui attend les touches claviers .. code-block:: python import colorconsole, colorconsole.terminal import sys import datetime import time import random import msvcrt import threading list_color = colorconsole.terminal.colors.keys() def randomColor(): return list_color[int(random.random() * len(list_color))] fgcolorrandom = randomColor() def listen(): global fgcolorrandom while 1: char = msvcrt.getch() if char == 'c': fgcolorrandom = randomColor() term = colorconsole.terminal.get_terminal() term.set_title('test') columns = term._Terminal__get_console_info().srWindow.Right - term._Terminal__get_console_info().srWindow.Left +1 lines = term._Terminal__get_console_info().srWindow.Bottom - term._Terminal__get_console_info().srWindow.Top +1 term.clear() term.reset() listener = threading.Thread(None, listen, None) listener.start() try: while(True): now = datetime.datetime.now() x = random.randint(1,columns-20) y = random.randint(1,lines) term.set_color(fg=colorconsole.terminal.colors[fgcolorrandom], bk=colorconsole.terminal.colors["BLACK"]) term.print_at(x,y,now.strftime("%d/%m/%Y %H:%M:%S")) term.set_color(fg=colorconsole.terminal.colors["WHITE"], bk=colorconsole.terminal.colors["BLACK"]) time.sleep(1) term.clear() term.reset() except KeyboardInterrupt: pass term.clear() term.reset() term.restore_buffered_mode() il est donc possible d'imaginer un listener en forme de classe avec une gestion de file (via le module Queue) les key-code a utiliser sont === ============================== Dec Abbr === ============================== 0 Null character 1 Start of Header 2 Start of Text 3 End of Text 4 End of Transmission 5 Enquiry 6 Acknowledgment 7 Bell 8 Backspace[d][e] 9 Horizontal Tab[f] 10 Line feed 11 Vertical Tab 12 Form feed 13 Carriage return[g] 14 Shift Out 15 Shift In 16 Data Link Escape 17 Device Control 1 (oft. XON) 18 Device Control 2 19 Device Control 3 (oft. XOFF) 20 Device Control 4 21 Negative Acknowledgement 22 Synchronous idle 23 End of Transmission Block 24 Cancel 25 End of Medium 26 Substitute 27 Escape[i] 28 File Separator 29 Group Separator 30 Record Separator 31 Unit Separator 32 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' 40 ( 41 ) 42 \* 43 \+ 44 , 45 \- 46 . 47 / 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G 72 H et fleche Haut 73 I 74 J 75 K et fleche Gauche 76 L 77 M er fleche Droite 78 N 79 O 80 P et fleche Bas 81 Q 82 R 83 S 84 T 85 U 86 V 87 W 88 X 89 Y 90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ 96 ``` 97 a 98 b 99 c 100 d 101 e 102 f 103 g 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w 120 x 121 y 122 z 123 { 124 pipe more 125 } 126 ~ 127 DEL === ============================== Redimensionner la console windows --------------------------------- Il est parfois utile de pouvoir redimensionner la console windows. Le script suivant fait cela très bien .. code-block:: python def console_resize(width=80, height=24, buffer_height=600): '''Sets up the console size and buffer height. param width {int} Width of console in column value. param height {int} Height of console in row value. param buffer_height {int} Buffer console height in row value. ''' from ctypes import windll, byref, create_string_buffer from ctypes.wintypes import SMALL_RECT, _COORD # Active console screen buffer # STD_OUTPUT_HANDLE -> -11, STD_ERROR_HANDLE -> -12) STDERR = -12 # SMALL_RECT input LEFT = 0 TOP = 0 RIGHT = width - 1 BOTTOM = height - 1 # handle hdl = windll.kernel32.GetStdHandle(STDERR) csbi = create_string_buffer(22) res = windll.kernel32.GetConsoleScreenBufferInfo(hdl, csbi) if res: import struct (bufx, bufy, curx, cury, wattr, left, top, right, bottom, maxx, maxy) = struct.unpack("hhhhHhhhhhh", csbi.raw) current_width = right - left + 1 current_height = bottom - top + 1 current_buffer_height = bufy if buffer_height < height: buffer_height = height # order of resizing avoiding some problems if current_buffer_height > buffer_height: rect = SMALL_RECT(LEFT, TOP, RIGHT, BOTTOM) # (left, top, right, bottom) windll.kernel32.SetConsoleWindowInfo(hdl, True, byref(rect)) bufsize = _COORD(width, buffer_height) # columns, rows windll.kernel32.SetConsoleScreenBufferSize(hdl, bufsize) else: bufsize = _COORD(width, buffer_height) # columns, rows windll.kernel32.SetConsoleScreenBufferSize(hdl, bufsize) rect = SMALL_RECT(LEFT, TOP, RIGHT, BOTTOM) # (left, top, right, bottom) windll.kernel32.SetConsoleWindowInfo(hdl, True, byref(rect)) console_resize()