2009-06-02 9 views
3

Actuellement, j'ai un simple robot IRC écrit en python.Bogue Python IRC et problème de codage

Depuis que je migré à Python 3.0 qui différencie entre les octets et les chaînes unicode j'ai commencé à avoir des problèmes de codage. Plus précisément, avec d'autres ne pas envoyer UTF-8.

Maintenant, je pourrais simplement dire à tout le monde d'envoyer UTF-8 (ce qu'ils devraient faire) mais une meilleure solution serait d'essayer de faire passer python par défaut à un autre type d'encodage.

Jusqu'à présent, le code ressemble à ceci:

data = str(irc.recv(4096),"UTF-8", "replace") 

Ce qui au moins ne jette pas des exceptions. Cependant, je veux aller au-delà: je veux que mon bot par défaut à un autre encodage, ou essayer de détecter des «caractères gênants» en quelque sorte.

De plus, je dois comprendre ce que ce mystérieux encodage que mIRC utilise est en fait - comme d'autres clients semblent fonctionner correctement et envoyer UTF-8 comme ils le devraient.

Comment dois-je faire ces choses?

Répondre

-1

Ok, après quelques recherches se révèle chardet a des problèmes avec python 3. La solution comme il se avère est plus simple que ce que je pensais. J'ai choisi de se replier sur CP1252 si UTF-8 ne coupe pas:

data = irc.recv (4096) 
try: data = str(data,"UTF-8") 
except UnicodeDecodeError: data = str(data,"CP1252") 

Ce qui semble fonctionner. Bien qu'il ne détecte pas l'encodage, et donc si quelqu'un est entré avec un encodage qui n'est ni UTF-8 ni CP1252, j'aurai encore un problème.

Ceci est vraiment juste une solution temporaire.

+1

cp1252 semblera toujours fonctionner pour toute séquence d'octets non nulle, car il affecte un point de code à chaque valeur d'octet sauf zéro. – RichieHindle

3

chardet devrait aider - c'est la bibliothèque Python canonique pour détecter les codages inconnus.

+0

Essayer maintenant. Je vais voir où ça me mène. – cwj

0

Le chardet sera probablement votre meilleure solution comme RichieHindle mentionné. Toutefois, si vous voulez couvrir environ 90% du texte, vous verrez que vous pouvez utiliser ce que j'utilise:

def decode(bytes): 
    try: 
     text = bytes.decode('utf-8') 
    except UnicodeDecodeError: 
     try: 
      text = bytes.decode('iso-8859-1') 
     except UnicodeDecodeError: 
      text = bytes.decode('cp1252') 
    return text 


def encode(bytes): 
    try: 
     text = bytes.encode('utf-8') 
    except UnicodeEncodeError: 
     try: 
      text = bytes.encode('iso-8859-1') 
     except UnicodeEncodeError: 
      text = bytes.encode('cp1252') 
    return text 
0

En utilisant seulement chardet conduit à de mauvais résultats pour les situations où les messages sont courts (ce qui est le cas dans IRC).

Chardet combinée à se rappeler le codage utilisateur spécifique à travers les messages pourraient donner un sens. Cependant, pour des raisons de simplicité, j'utiliserais des encodages présumables (les encodages dépendent de la culture et de l'époque, voir http://en.wikipedia.org/wiki/Internet_Relay_Chat#Character_encoding) et s'ils échouent, je passerais à chardet (si quelqu'un utilise des encodages d'Asie de l'Est, cela nous aidera).

Par exemple:

def decode_irc(raw, preferred_encs = ["UTF-8", "CP1252", "ISO-8859-1"]): 
    changed = False 
    for enc in preferred_encs: 
     try: 
      res = raw.decode(enc) 
      changed = True 
      break 
     except: 
      pass 
    if not changed: 
     try: 
      enc = chardet.detect(raw)['encoding'] 
      res = raw.decode(enc) 
     except: 
      res = raw.decode(enc, 'ignore') 
return res 
+0

Cette tentative de faire 'res = raw.decode ('U')' abandonne alors rapidement. –