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
mydata = raw_input('Prompt :')
print (mydata)
- ::
- C:UsersfraoustinDesktop>python test3.py Prompt :coucou coucou
Création d’un interpréteur¶
Il faut pour cela utiliser le module cmd.Cmd
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 <topic>):
========================================
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
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
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
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
def console_resize(width=80, height=24, buffer_height=600):
'''Sets up the console size and buffer height.
<at> param width {int} Width of console in column value.
<at> param height {int} Height of console in row value.
<at> 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()