Cette page présente un petit exemple de liaison entre Python et une librairie dynamique en C.

L'exemple choisi ici est l'implémentation d'un appel depuis Python à la fonction iconv de la librairie C.

(!) Documentation utilisée : http://docs.python.org/library/ctypes.html

Fichier /usr/local/lib/python2.5/site-packages/iconv.py :

   1 #!/usr/bin/env python
   2 # -*- coding: utf-8 -*-
   3 """
   4 Module de support iconv pour Python.
   5 
   6 Copyright : Agence universitaire de la Francophonie
   7 Licence : GNU General Public Licence, version 2
   8 Auteur : Jean Christophe André
   9 Date de création : 20 mars 2009
  10 """
  11 
  12 from ctypes import *
  13 from ctypes.util import find_library
  14 
  15 # on n'exporte que la fonction iconv ('a marche pô ?!)
  16 __all__ = ["iconv"]
  17 
  18 # la librairie C
  19 _libc = CDLL(find_library("c"))
  20 
  21 # un type spécifique à iconv (pour stoquer l'état de son automate)
  22 _iconv_t = c_void_p
  23 
  24 # prototype de la fonction iconv_open(3)
  25 _iconv_open = _libc.iconv_open
  26 _iconv_open.argtypes = [c_char_p, c_char_p]
  27 _iconv_open.restype = _iconv_t
  28 
  29 # prototype de la fonction iconv(3)
  30 _iconv = _libc.iconv
  31 _iconv.argtypes = [_iconv_t,
  32                    POINTER(POINTER(ARRAY(c_char, 1024))), POINTER(c_size_t),
  33                    POINTER(POINTER(ARRAY(c_char, 4096))), POINTER(c_size_t)]
  34 _iconv.restype = c_size_t
  35 
  36 # prototype de la fonction iconv_close(3)
  37 _iconv_close = _libc.iconv_close
  38 _iconv_close.argtypes = [_iconv_t]
  39 _iconv_close.restype = c_int
  40 
  41 def iconv(from_code, to_code, string):
  42     """
  43     from_code : encodage d'origine de string
  44     to_code : encodage souhaité en retour
  45     string : la chaîne dont il faut convertir l'encodage
  46 
  47     On pourra utiliser to_code='ascii//TRANSLIT' pour supprimer les accents.
  48     Attention : ça ne fonctionne pas à 100% avec les langues hors Latin-{N} !
  49 
  50     Plus de détails dans la page de manuel de iconv(1).
  51     """
  52 
  53     # on commence par créer un contexte de conversion
  54     cp = _iconv_open(c_char_p(to_code), c_char_p(from_code))
  55 
  56     # on prépare les structures de données à transmettres
  57     inbuf = create_string_buffer(string, 1024)
  58     inbytesleft = c_size_t(len(inbuf))
  59     p_inbuf = pointer(inbuf)
  60     outbuf = create_string_buffer(4096)
  61     outbytesleft = c_size_t(len(outbuf))
  62     p_outbuf = pointer(outbuf)
  63 
  64     # on effectue la conversion
  65     _iconv(cp, byref(p_inbuf), byref(inbytesleft),
  66                byref(p_outbuf), byref(outbytesleft))
  67     result = outbuf.value[:outbytesleft.value]
  68 
  69     # on détruit le contexte de conversion et on retourne le résultat
  70     _iconv_close(cp)
  71     return result
  72 
  73 if __name__ == "__main__":
  74     # on précise la translitération via un environnement linguistique
  75     from locale import setlocale, LC_ALL
  76     setlocale(LC_ALL, 'en_US.UTF-8')
  77 
  78     # test de cas limites (en français, vietnamien et japonais)
  79     from unicodedata import normalize
  80     t = u"fête cœur français tiếng việt đường プログフ"
  81     i = iconv("utf-8", "ascii//TRANSLIT", t.encode('utf-8'))
  82     u = normalize("NFKD", t).encode('ascii','ignore')
  83     print u"TEST: texte original: '%s'" % t
  84     print u"TEST: iconv(utf8..ascii//TRANSLIT): '%s'" % i
  85     print u"TEST: normalize(NFKD).encode(ascii,ignore): '%s'" % u

Lancement d'un test :

python /usr/local/lib/python2.5/site-packages/iconv.py

Résultat sur Ubuntu "Intrepid" 8.10 :

$ python iconv.py
TEST: texte original: 'fête cœur français tiếng việt đường プログフ'
TEST: iconv(utf8..ascii//TRANSLIT): 'fete coeur francais tieng viet ?uong ????'
TEST: normalize(NFKD).encode(ascii,ignore): 'fete cur francais tieng viet uong '

Exemple d'utilisation dans un programme :

   1 #!/usr/bin/env python
   2 # -*- coding: utf-8 -*-
   3 
   4 from iconv import iconv
   5 from locale import setlocale,LC_ALL
   6 
   7 setlocale(LC_ALL, 'fr_FR.UTF-8')
   8 
   9 texte_utf8 = u"fête cœur français".encode("utf-8")
  10 texte_sans_accent = iconv("utf-8", "ascii//TRANSLIT", texte_utf8)
  11 
  12 print u"Texte d'origine :", texte_utf8
  13 print u"Suppression des accents :", texte_sans_accent

Python/iconv (dernière édition le 2009-03-22 17:32:57 par JeanChristopheAndré)