Python - Corrigé du TD 2



Exercice 1


#!/usr/bin/env python
# -*- coding: iso-8859-15 -*-
'''
Mélange aléatoirement les lettres internes des mots d'un fichier
ou de l'entrée standard

Usage: blurr [<fichier> <encodage>]
'''
from random import shuffle

# le plus simple est de construire une liste des codes "latin1"
# de ce qu'on veut considérer comme des lettres.
# La méthode "decode" des chaînes convertit en unicode
# On peut ensuite réencoder en ce qu'on veut :
### >>> 'é'.decode('utf8').encode('latin1')
### '\xe9'

letters = [
    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
    'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
    'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
    'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
    '\xa6', '\xa8', '\xaa', '\xb4', '\xb5', '\xb8', '\xba', '\xbc',
    '\xbd', '\xbe', '\xc0', '\xc1', '\xc2', '\xc3', '\xc4', '\xc5',
    '\xc6', '\xc7', '\xc8', '\xc9', '\xca', '\xcb', '\xcc', '\xcd',
    '\xce', '\xcf', '\xd0', '\xd1', '\xd2', '\xd3', '\xd4', '\xd5',
    '\xd6', '\xd8', '\xd9', '\xda', '\xdb', '\xdc', '\xdd', '\xde',
    '\xdf', '\xe0', '\xe1', '\xe2', '\xe3', '\xe4', '\xe5', '\xe6',
    '\xe7', '\xe8', '\xe9', '\xea', '\xeb', '\xec', '\xed', '\xee',
    '\xef', '\xf0', '\xf1', '\xf2', '\xf3', '\xf4', '\xf5', '\xf6',
    '\xf8', '\xf9', '\xfa', '\xfb', '\xfc', '\xfd', '\xfe', '\xff']
 
# On lira ensuite tout le fichier, ou l'entrée standard, sous forme d'une
# seule chaîne s. La fonction suivante examine chaque caractère de s.
# Si ce n'est pas une lettre, elle l'insère dans une liste ll, qui sera
# convertie en chaîne à la fin. Si c'est une lettre, elle l'insère dans
# une liste mm, ainsi que toutes les lettres suivantes. Dès qu'on rencontre
# un autre caractère, on mélange les lettres internes de mm, et on concatène
# le résultat à ll:

def blurr(s):
    ll = []; i=0
    while i in range(len(s)):
        mm=[]
        while i < len(s) and s[i] in letters:
            mm.append(s[i])
            i+=1
        if mm:
            if len(mm)>3:
                uu=mm[1:-1]; shuffle(uu)  # s'applique à une liste
                ll+=[mm[0]]+uu+[mm[-1]]   # et la modifie
            else:
                ll+=mm
            continue
        else:
            while i < len(s) and s[i] not in letters:
                ll.append(s[i])
                i+=1
    return ''.join(ll)


if __name__=="__main__":
# arguments: <fichier> <encodage>
    import sys
    
    if len(sys.argv)>2:  
    s = open(sys.argv[1],'r').read()
    e = sys.argv[2]
    t = unicode(blurr(s), e)
        print t
# ou alors l'entrée standard        
    else:
        s = raw_input('texte: ')
        print '--->  ', blurr(s)
        
    
            
Le cours 2 montre une solution plus efficace utilisant des expressions rationnelles.
#!/usr/bin/env python

import random, re, sys

p = re.compile('(\w)(\w+)(\w)', re.M|re.L|re.U)

def touille(m):
    milieu = list(m.group(2))
    random.shuffle(milieu)
    return m.group(1) + ''.join(milieu) + m.group(3)

if len(sys.argv)==4:
    s = open(sys.argv[1]).read().decode(sys.argv[2])
    t = p.sub(touille, s).encode(sys.argv[3])
    sys.stdout.write(t)
else:
    print "Usage: touille <fichier> <encodage> <encodage>"


Pour construire la liste "letters" sans se fatiguer :


# A exécuter ligne à ligne dans l'intérpréteur
# On construit une liste de tous les caractères encodables en latin1
s=''.join([chr(i).decode('latin1') for i in range(256)])
# On l'imprime
print s  
# On efface ce qui n'est pas une lettre
# C'est vite fait car ça marche par tranches
t='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ'
# et voilà la liste cherchée
letters = [x.encode('latin1') for x in t.decode('utf8')]

print letters




Exercice 2


#!/usr/bin/env python
# -*- encoding: utf8 -*-
"""
Client pour serveur d'injures du capitaine Haddock, en xmlrpc (imite un exemple classique de SOAP)
"""


from xmlrpclib import ServerProxy

from base64 import *

server=ServerProxy("http://monge.univ-mlv.fr:8888")


if "__name__==__main__":
    print __doc__
    print "Methodes du serveur:\n"
    for m in  server.system.listMethods(): print m
    print
    print "Un appel de server.jure() donne: ", server.jure()
    print "C'est en base 64, il faut decoder: "
    print "\n\t"+decodestring(server.jure()).rstrip()+"!"
    open('insultes.txt','w').write(decodestring(server.tous_les_jurons()))
    print "Liste récupérée!"
    
# Un peu de curiosité permet de récupérer le code du serveur
    print "\n\t"+decodestring(server.__())


Code du serveur :


# -*- coding: iso-8859-15 -*-
#!/usr/bin/env python

"""
Serveur d'injures du capitaine Haddock. Utilise le
protocole xmlrpc. Le données sont encodées en
base 64 à cause des caracteres accentués.
"""


from SimpleXMLRPCServer import SimpleXMLRPCServer as Server
from random import randint        

jurons=open('jurons.txt','r').readlines()

def jure():
        return jurons[randint(0,len(jurons))].encode('base64')

def help(): return  "ENCODAGE=BASE64"

def __():
    s=open('haddockServer.py','r').read()
    return s.encode('base64')

def tous_les_jurons():
    s=open('jurons.txt','r').read()
    return s.encode('base64')

server = Server(('193.55.63.80', 8888))

server.register_function(tous_les_jurons)
server.register_function(jure)
server.register_function(help)
server.register_function(__)
server.register_introspection_functions()

try:
    server.serve_forever()
finally:
    server.server_close()