L’API Python permet une gestion souple et complète des fichiers CSVM, elle est opérationnelle depuis le début des années 2000, et succède à une couche expérimentale écrite en Perl. Les codes Python sont regroupés dans les paquetages buildez.parsers (primitives) et buildez.wrappers (composants de niveau supérieur et applications complètes en mode ligne de commande ou scriptables). Cet article présente brièvement les modules impliqués dans le paquetage buildez.parsers et donnera une idée de la programmation qui en découle.
Publications initiales : buidez.net (2012), rapports techniques sur arXiv (2012) – Version refondue et mise à jour en 2024-2025.
1. Le toolkit CSVM Python
L’ensemble des modules du groupe parsers inclue une centaine de fonctions ou méthodes, destinées à interagir avec un objet csvm_ptr, différents types de fichiers, des opérations sur les tables CSVM. Ces fonctions sont distribuées sur 8 modules :
csvm |
Le module de base qui inclue l’objet csvm_ptr, la lecture de fichiers, chaines (string) CSVM, la même chose en export (CSVM + CSV), la conversion de dictionnaires Python. Des fonctions pour les colonnes : recherche, import dans une liste, insertion, suppression, copie, déplacement. Des fonctions de comparaison de colonnes (déplacées dans query). |
csvm_csv |
L’import de fichiers CSV en utilisant un dictionnaire CSVM, l’export vers le format CSV (en mode string ou fichier). |
csvm_meta |
La surcharge d’informations dans la table ou les métadonnées, la conservation des commentaires. |
csvm4csv |
Des macros pour la conversion CSVM vers CSVM avec un paramétrage plus complexe (passant par une structure arg_ptr) que dans le module csvm_csv. |
csvm4xml |
L’équivalent de csvm4csv pour l’export en XML. |
csvmdict |
Le chargement de dictionnaires CSVM dans un objet csvm_ptr, les filtres d’application d’un dictionnaire CSVM à un fichier CSVM. |
csvmutil |
L’insertion de doubles colonnes (ex: clé – valeurs) dans une table, la recherche de colonnes similaires dans deux objets CSVM, l’intersection et l’union de deux tables, le changement de nom ou la suppression de lots de colonnes. |
query |
Des tests d’égalité de cellules simples (eq) ou multiples au sein de colonnes, d’égalité de colonnes entières. Les mêmes tests en mode non égalité (not eq). Les mêmes tests pour des lignes simples ou multiples. |
En 2025 csv est devenu csvm_csv et j’ai inclus csvm_meta, d’autres modules sont en cours de développement. Il n’y a pas d’outils de conversion de types ou de tris de colonnes car ils sont inclus dans d’autres modules (ex: strmatrix) dédiés aux vecteurs et matrices de chaines de caractères.
2. L’objet csvm_ptr en Python
L’objet csvm_ptr est défini dans le module csvm.py et présente des champs analogues à ceux de la version Perl : source, titre, en-têtes, types, largeurs, données organisées en matrice et métadonnées …
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
class csvm_ptr: """ Follows CSVM specs (v:1.x) for contents of data structure. Standard column types are NUMERIC,TEXT,DATE,BOOLEAN. Some of us, use also INTEGER, FLOAT for numeric types. Some of us, use also NODE, LINK, IMAGE for web data embedded in CSVM files. WIDTHs (10,50 if not set) are for Javascript tables and can be omitted. Extended (2017) with support of remarks in CSVM file. *** 1.01/080304/fred *** 1.03/160617/fred *** 1.04/240724/Fred """ def __init__(self): self.SOURCE = "" # Path/file name of readed CSVM file self.CSV = "" # CSVM or CSV depending of file contents self.TITLE_N = 0 # Titles of CSVM file (let for future, only one string used today) self.TITLE = "" # Title of CSVM file self.HEADER_N = 0 # Number of data columns titles self.HEADER = [] # List of data column titles self.TYPE_N = 0 # Number of data columns types (= self.HEADER_N) self.TYPE = [] # List of data column types self.WIDTH_N = 0 # Number of data columns widths (= self.HEADER_N) self.WIDTH = [] # List of data column widths self.DATA_R = 0 # Number of data rows self.DATA_C = 0 # Number of data columns (= self.HEADER_N) self.DATA = [] # String matrix containing data self.META = "" # Meta string self.RTABLE_N = 0 # Number of remark blocks self.RTABLE = [] # Table of remarks (blocks) self.LSEP = "\n" # Chars used for end of lines (lsep) self.FSEP = "\t" # Chars used as field separator (fsep) self.BLANK = "-" # Chars used for empty (blank) cells self.EMPTY = "#_REM_" # Marker for empty (BLANK) lines self.REMARKS = "" # Used for store infos about CSVM structure ... |
Au fur et à mesure des expérimentations des champs ont été ajoutés, soit ils sont plus précis, soit ils permettent le support d’extensions du parseur. Par exemple la conservation d’annotations présentes dans le fichier que l’on trouve dans self.RTABLE (et self.RTABLE_N pour le nombre de lignes de la table de remarques) qui n’existaient pas dans le parseur Perl.
3. Quelques exemples en Python
L’API Python permet une gestion souple et complète des fichiers CSVM. Par exemple, nous instancier un objet csvm_ptr et l’utiliser pour lire le contenu d’un fichier CSVM (affiché avec SciTE). Il s’agit d’une mini collection de produits chimiques, avec 15 colonnes (la visibilité des fins de ligne CRLF est activée) :
![]() |
La séquence des opérations utilise deux fonctions : csvm_ptr pour créer l’objet c de type csvm_ptr, puis csvm_ptr_read_extended_csvm pour lire le fichier (délimité par des tabulations) et identifié par la variable fname.
|
1 2 3 4 5 6 |
print("*** A new blank CSVM structure") c = csvm_ptr() print("*** Read test.csvm and fills the structure ...") c = csvm_ptr_read_extended_csvm(c, fname, "\t") print("*** Dump all ... ") c.csvm_ptr_dump(0,0) |
La méthode csvm_ptr_dump avec les paramètres (0,0) permettra d’afficher la table, par exemple :
![]() |
D’autres options de csvm_ptr_dump permettent de réduire l’affichage, à la manière de la librairie Pandas de Python, ou de n’imprimer que certaines lignes du bloc DATA.
Recherche ou extraction de colonnes
Une fois que nous avons l’objet nous pouvons interagir avec lui, par exemple réaliser des extractions de colonnes. Les fonctions csvm_ptr_str_getvec (mode string) et csvm_ptr_getvec (mode liste) permettent de sortir une colonne en se basant sur son indice. Par exemple la colonne 1 (correspondant au #HEADER ‘fichier_mol‘) en mode string :
|
1 2 3 4 5 |
print("*** Extract the second column (numbered as 1 in CSVM)") print("-> as string with a separator '|'") print(csvm_ptr_str_getvec(c,0,2,"|")) print("-> as vector (Python list) of strings") print(csvm_ptr_getvec(c, 0, 2)) |
Ce qui nous donne comme résultat :
*** Extract the second column (numbered as 1 in CSVM)-> as string with a separator '|'af01.mol|af02.mol|af03.mol|af04.mol|af05.mol|af06.mol-> as vector (Python list) of strings['af01.mol', 'af02.mol', 'af03.mol', 'af04.mol', 'af05.mol', 'af06.mol'] |
Nous pouvons aussi faire un test sur la valeur des champs #HEADER avec la fonction csvm_ptr_getcol qui va renvoyer une liste incluant les colonnes possibles, précédées par le nombre de colonnes. Si l’interrogation est bien faite nous n’aurons qu’une liste [1, colx] ou colx est la liste des valeurs de la colonne trouvée. Par exemple :
|
1 2 3 4 5 6 7 8 9 10 |
print("*** Extract columns on the value of headers") print("-> the column named 'fichier_mol' in strict mode") ls = csvm_ptr_getcol(c, 'fichier_mol', 1) print("found %d column in CSVM stream" % (ls[0])) print(ls[1]) print("-> the columns in which string 'no_' is found") ls = csvm_ptr_getcol(c, 'no_', 0) print("found %d columns in CSVM stream" % (ls[0])) for i in range (1, ls[0]+1, 1): print(i, ls[i]) |
Ce type de fonction peut être utilisée en mode strict (égalité de la chaine de test avec le titre de colonne) ou non (la chaine de test doit être incluse dans le titre de colonne). Ce qui nous donne une seule colonne pour ‘fichier_mol‘ (strict) et 3 colonnes (not strict) pour ‘no_‘ car nous avons ‘no_equipe‘, ‘no_boite‘, ‘no_col_boite‘ dans les valeurs de #HEADER :
*** Extract columns on the value of headers-> the column named 'fichier_mol' in strict modefound 1 column in CSVM stream['af01.mol', 'af02.mol', 'af03.mol', 'af04.mol', 'af05.mol', 'af06.mol']-> the columns in which string 'no_' is foundfound 3 columns in CSVM stream1 ['1', '1', '1', '-', '1', '-']2 ['1', '1', '1', '-', '1', '-']3 ['1', '1', '1', '-', '3', '-'] |
Intersection et union de tables
Le code pour une union ou une intersection est simple, prenons le cas de deux objets CSVM c1 et c2 qui ont étés lus avec csvm_ptr_read_extended_csvm, nous avons :
|
1 2 3 4 5 6 7 8 9 10 |
print("=> Compute INTERSECTION") r = csvm_ptr_intersect(c1, c2) r.csvm_ptr_dump(0,0) r.csvm_ptr_clear() print("\n=> compute UNION") r = csvm_ptr_union(c1, c2) r.csvm_ptr_dump(0,0) r.csvm_ptr_clear() c1.csvm_ptr_clear() c2.csvm_ptr_clear() |
Le résultat de l’intersection ou de l’union est également un objet csvm_ptr. Ces deux processus sont basés sur les identifiants de colonnes, si celles ci sont de longueur différentes, les colonnes courtes sont complétées par un caractère à spécifier (généralement équivalent à self.BLANK de l’objet csvm_ptr).
4. Conclusion
Il ne s’agit que de quelques exemples destinés à appréhender l’API et qui ne concernent que des aspects purement CSVM. Il existe des interfaces CSVM plus ou moins riches vis à vis d’autres processus, mais les fonctions correspondantes sont dispersées dans d’autres groupes fonctionnels. Par exemple : gestion de tables chimiques via différents toolkits chimiques (Openbabel/Pybel, RDKit), gestion d’index, de coordonnées et d’interactions moléculaires, interface avec la librairie Pandas (calculs numériques, représentations graphiques) ….

