Interpreteur Python

Il existe de nombreux interpreteur Python:

  • bpyton
  • jython
  • pypy
  • ipython

Il propose tous une coloration synthaxique et une aide en ligne.

Il possède aussi, suovant les interpreteurs, des caractéristiques propres:

  • gestion en temps réel des interfaces graphiques (ipython)
  • une implémentation pure python (pypy), java (jython), dotnet (ipython)

Le principale soucis des ces interpreteurs, à mon avis, est qu’il ne s’agit pas de l’interpreteur original python et on peut donc avoir des comportements non désirés

Python embarque son propre interpreteur qu’il est possible de lancer ainsi

python

Note

Il faut noter que le binaire python doit être dans votre path pour réaliser cette opération. si vous avez plusieurs versions de python sur votre poste faite bien attention à la version lancé

Ajout de l’autocomplémentation

uniquement disponible sous linux il est possible d’ajouter nativement l’autocomplémentation par l’utilisation de la tabulation. Pour cela il suffit de lancer les commandes suivantes

import readline
import rlcompleter
readline.parse_and_bind("tab: complete")

Il est possible que ce code soit lancé à chaque lancement de l’interpreteur via PYTHONSTARTUP (cf gestion avancé)

gestion des multi-interpreteurs

Le principe est de créer des alias dans votre environnements

sous linux il faut modifier votre .bashrc afin d’ajouter par exemple

alias python3 = "\usr\bin\python33"

sous windows il faut modifier le fichier qui gère vos alias

@doskey python3="C:\Python\Python33\python.exe" $*
@doskey python27="C:\Python\Python27\python.exe" $*

Pour pluys d’infos sur la gestion des alias sous windows ajout d’alias dans MS-DOS

gestion avancé

Le paragraphe qui suit est basé sur l’utilisation de la variable PYTHONSTARTUP.

Cette variable peut contenir le path d’un fichier python a lancer à chaque lancement de l’interpreteur de façon automatique.

sous linux vous pouvez ajouter cette ligne dans le .bashrc

export PYTHONSTARTUP=~HOME\.pythonstartup.py

sous windows

set PYTHONSTARTUP=C:\Users\f.aoustin.PROPLAST\.pythonstartup.py
_images/20130306_01.png

ou encore en utilisant le fichier de gestion des alias ajout d’alias dans MS-DOS

@echo off
set PYTHONSTARTUP=C:\Users\f.aoustin.PROPLAST\pythonstartup.py

L’interpreteur peut être modifier de plusieurs façon.

Par exemple il est possible de rendre son prompt dynamique

class LineCounter(object):
    def __init__(self):
        self.count = 0
    def __str__(self):
        self.count += 1
        return '%d>' % self.count

class LineCounterSpace(object):
    def __init__(self, ps):
        self._ps = ps
    def __str__(self):
        return ' ' * (len(str(self._ps.count))+1)

sys.ps1 = LineCounter()
sys.ps2 = LineCounterSpace(sys.ps1)

maintenant chaque ligne est incrémenter d’un nombre

Pour moi un interpreteur doit pouvoir avoir:

  • une coloration différente pour les sorties erreur ou normale
  • fournir une doc complète des objets manipulés

Si sous linux cela est évident, sous windows cela est plus difficile

on peut donc utilisé comme fichier de startuppython le code suivant

"""

use color_console.py
from http://www.burgaud.com/bring-colors-to-the-windows-console-with-python/

"""

from ctypes import windll, Structure, c_short, c_ushort, byref
import sys, os

SHORT = c_short
WORD = c_ushort

class COORD(Structure):
    """struct in wincon.h."""
    _fields_ = [
        ("X", SHORT),
        ("Y", SHORT)]

class SMALL_RECT(Structure):
    """struct in wincon.h."""
    _fields_ = [
        ("Left", SHORT),
        ("Top", SHORT),
        ("Right", SHORT),
        ("Bottom", SHORT)]

class CONSOLE_SCREEN_BUFFER_INFO(Structure):
    """struct in wincon.h."""
    _fields_ = [
        ("dwSize", COORD),
        ("dwCursorPosition", COORD),
        ("wAttributes", WORD),
        ("srWindow", SMALL_RECT),
        ("dwMaximumWindowSize", COORD)]

# winbase.h
STD_INPUT_HANDLE = -10
STD_OUTPUT_HANDLE = -11
STD_ERROR_HANDLE = -12

# wincon.h
FOREGROUND_BLACK     = 0x0000
FOREGROUND_BLUE      = 0x0001
FOREGROUND_GREEN     = 0x0002
FOREGROUND_CYAN      = 0x0003
FOREGROUND_RED       = 0x0004
FOREGROUND_MAGENTA   = 0x0005
FOREGROUND_YELLOW    = 0x0006
FOREGROUND_GREY      = 0x0007
FOREGROUND_INTENSITY = 0x0008 # foreground color is intensified.

BACKGROUND_BLACK     = 0x0000
BACKGROUND_BLUE      = 0x0010
BACKGROUND_GREEN     = 0x0020
BACKGROUND_CYAN      = 0x0030
BACKGROUND_RED       = 0x0040
BACKGROUND_MAGENTA   = 0x0050
BACKGROUND_YELLOW    = 0x0060
BACKGROUND_GREY      = 0x0070
BACKGROUND_INTENSITY = 0x0080 # background color is intensified.

stdout_handle = windll.kernel32.GetStdHandle(STD_OUTPUT_HANDLE)
stdin_handle = windll.kernel32.GetStdHandle(STD_INPUT_HANDLE)
stderr_handle = windll.kernel32.GetStdHandle(STD_ERROR_HANDLE)
SetConsoleTextAttribute = windll.kernel32.SetConsoleTextAttribute
GetConsoleScreenBufferInfo = windll.kernel32.GetConsoleScreenBufferInfo

def get_text_attr():
    """Returns the character attributes (colors) of the console screen
    buffer."""
    csbi = CONSOLE_SCREEN_BUFFER_INFO()
    GetConsoleScreenBufferInfo(stdout_handle, byref(csbi))
    return csbi.wAttributes

def set_text_attr(color):
    """Sets the character attributes (colors) of the console screen
    buffer. Color is a combination of foreground and background color,
    foreground and background intensity."""
    SetConsoleTextAttribute(stdout_handle, color)
    SetConsoleTextAttribute(stderr_handle, color)
    SetConsoleTextAttribute(stdin_handle, color)



DEFAULT_PRINT_ERR = FOREGROUND_RED
DEFAULT_PRINT_OUT = FOREGROUND_GREEN
DEFAULT_PRINT_IN = FOREGROUND_YELLOW
DEFAULT_PRINT_DOC = FOREGROUND_MAGENTA
DEFAULT_COLORS = get_text_attr()
DEFAULT_BG = DEFAULT_COLORS & 0x0070

class Unbuffered:
    def __init__(self, stream, colorprint):
        self.stream = stream
        self.colorprint = colorprint
        self.line_buffering=False
    def write(self, data):
        set_text_attr(self.colorprint | DEFAULT_BG | FOREGROUND_INTENSITY)
        self.stream.write(data)
        self.stream.flush()
        set_text_attr(DEFAULT_COLORS)
    def __getattr__(self, attr):
        return getattr(self.stream, attr)

sys.stdout=Unbuffered(sys.stdout, DEFAULT_PRINT_OUT)
sys.stderr=Unbuffered(sys.stderr, DEFAULT_PRINT_ERR)
sys.stdin=Unbuffered(sys.stdin, DEFAULT_PRINT_IN)

class ExpressionDoc(object):
    def __call__(self, value):
        set_text_attr(DEFAULT_PRINT_DOC | DEFAULT_BG | FOREGROUND_INTENSITY)
        if value not in (None, clear, cls):
            try:
                sys.stdout.stream.write(value.__doc__ + '\n\n')
            except:
                pass
            try:
                sys.stdout.stream.write('Class: %s\n\n' % value.__class__.__name__)
            except:
                pass
            try:
                sys.stdout.stream.write('List of attributes:\n')
                for i,j in value.__dict__:
                    sys.stdout.stream.write('\t%s : %s\n' % (i, str(j)))
                sys.stdout.stream.write('\n')
            except:
                pass
            try:
                sys.stdout.stream.write('List of functions:\n\t')
                sys.stdout.stream.write('\n\t'.join(dir(value))+'\n')
            except:
                pass
        else:
            sys.__displayhook__(value)
        sys.stdout.stream.flush()
        set_text_attr(DEFAULT_COLORS)

sys.displayhook = ExpressionDoc()

class PromptPs(object):
    def __init__(self, prt):
        self._prt = prt
        self.count = 0

    def __str__(self):
        self.count = self.count + 1
        set_text_attr(DEFAULT_PRINT_IN | DEFAULT_BG | FOREGROUND_INTENSITY)
        sys.stdout.stream.write('%d%s' % (self.count,self._prt))
        sys.stdout.stream.flush()
        set_text_attr(DEFAULT_COLORS)
        return None

class PromptPsSpace(object):
    def __init__(self, ps):
        self._ps = ps
    def __str__(self):
        return ' ' * (len(str(self._ps.count))+len(self._ps._prt))

sys.ps1 = PromptPs(' >>')
sys.ps2 = PromptPsSpace(sys.ps1)

class cls(object):
    def __repr__(self):
        sys.ps1.count = 0
        os.system('cls' if os.name == 'nt' else 'clear')
        return ''

cls = cls()

class clear(object):
    def __repr__(self):
        sys.ps1.count = 0
        os.system('cls' if os.name == 'nt' else 'clear')
        return ''

clear = clear()

avant:

_images/20130306_02.png

après:

_images/20130306_03.png

d’un coup cela est plus clair