Blog Haypo

Aller au contenu | Aller au menu | Aller à la recherche

mardi 14 août 2007

État des lieux de Python 3000

Profitant de mes vacances, j'ai testé Python 3000 (relire mon billet précédent sur Python 3000) pour voir si c'était utilisable. Autant ne pas se mentir : Python 3000 n'est pas prêt pour un usage quotidient. Selon moi, il y avait deux évolutions majeures et pénibles (pour les développeurs CPython) : fusion des types int et long, et la distinction entre les types bytes et str (anciennement str et unicode).

Types int et long

Pour les types int et long, en fait c'est le type long est renommé int et le l'ancien type int disparait. Pour les programmmeurs Python, on aura plus besoin d'écrire « isinstance(valeur, (int, long)) » pour vérifier si une valeur est un entier : « isinstance(valeur, int) » est désormais suffisant. Le suffixe L indiquant qu'un nombre est un entier long disparait également.

Pour la manipulation des entiers, Python 2.4 était déjà une avancée majeure. Si le résultat d'un calcul sur des entiers courts (int) dépasse la capacité d'un entier court, une conversion automatique en entier long est réalisée. Exemple : 2 ** 100 (où 2 et 100 sont des entiers courts) retourne 1267650600228229401496703205376L (type long).

Selon moi, Python va dans le bon sens : s'abstraire des limitations matérielles pour simplifier la vie au développeur. Python s'occupe tout seul des tâches pénibles : allouer la mémoire, faire des calculs sur les entiers longs, etc.

Types bytes et str

La distinction entre octet et caractère est un changement majeur dans Python. La compatibilité est brisée car le type bytes n'a plus les méthodes relatives à la manipulation de caractère telle que lower() et splitlines(), et un élément d'une chaîne bytes est un entier et non pas une sous-chaîne bytes. Exemple : b'xyz'[0] retourne 120. C'est d'ailleurs déroutant car le test « b'xyz'[0] == b'x' » est faux (120 == b'x' est faux). Il faut écrire explicitement « b'xyz'[0] == ord(b'x') » ou « b'xyz'[0] == 120 ».

La tâche est quasiment terminée : la branche subversion py3k-struni qui lui était dédiée a été fusionnée dans la branche py3k (branche python 3000 officielle). Il reste quelques bogues en particulier le module « email » qui est loin de fonctionnner en Python 3000.

J'ai aidé en corrigeant les modules ctypes, imghdr et sndhdr. Voir les commits 56838 (ctypes) et 56987 (imghdr et sndhdr). J'ai tenté avec beaucoup de mal de migrer le module email, mais comme il est assez gros et mélange allégrement octet et caractère, c'est loin d'être terminé. J'ai envoyé plusieurs emails à la liste de diffusion email-sig mais j'ai eu peu de retours.

Python 3000 ça sort quand ?

Une partie du wiki Python est dédiée à Python 3000 où on trouve en particulier les articles Py3kToDo (ce qu'il reste à faire dans Python 3000) et Py3kStrUniTests (tests unitaires cassés par la distinction bytes/str). La PEP 3100 (Miscellaneous Python 3.0 Plans) liste également toutes les tâches à faire pour Python 3000 avec leur état : [done] (fait), [UNLIKELY] (tâché en discussion), [no] (tâche refusée).

Migration à MediaWiki 1.10 et réduction de la taille de la base MySQL

J'ai reçu récemment un email indiquant que ma base de donnée haypocalc.com atteignait 90% du quota de 25 Mo. J'ai rapidement suspecté mon wiki de monopoliser toute la place dans MySQL. Je sais que MediaWiki, logiciel gérant le wiki, est très gourmant en place : chaque révision d'une page est stockée intégralement dans la base de donnée et non pas juste les changements.

Changement de contrat

La première chose qui m'a choqué est que les termes de mon contrat OVH, une offre d'hébergement « 300GP » (GP pour Grand Public), avaient changé. Pour preuve, en 2003 l'offre comportait « espace MySQL illimité », alors qu'aujourd'hui il y a un quota de 25 Mo. Je n'ai pas été informé de ce changement. Il existe des options pour avoir 100 ou 250 Mo de base MySQL, mais ça se paie très cher : respectivement 72€ et 144€ (prix TTC par an). Un mauvais point pour OVH.

La grosse boulette

J'ai alors commencé par faire une sauvegarde de la base. Par expérience, j'ai appris à toujours sauvegarder avant de faire une opération délicate (susceptible d'être une connerie).

Pour faire le ménage dans le wiki, j'ai décidé de vider la table MySQL « wiki_text » qui semblait ne contenir que les anciennes versions. Les noms des colonnes de cette table sont préfixés par « old » (ancien) alors que pour la table « wiki_cur », les noms des colonnes sont préfixés par « cur » (current, actuel). Manque de bol, j'ai alors cassé le wiki : impossible de modifier une page (le formulaire d'édition était vide) !

Je réalise que j'ai fait une boulette : j'aurai du la renommer plutôt que de la vider.

Tentative de restauration du SQL par phpMyAdmin

Pour restaurer la base MySQL, je commence par la vider (supprimer toutes les tables) et j'utilise le phpMyAdmin d'OVH pour envoyer la sauvegarde. Sachant que la taille maximale de l'envoi est de 8 Mo (compressé ou non), je compresse mon dump SQL de 22 Mo avec gzip. Le fichier tient dans 4 Mo, la taille est bonne : je l'envoie. Premier échec : timeout PHP.

J'installe alors phpMyAdmin dans mon hébergement pour résoudre le problème de timeout. J'ai passé la première épreuve mais j'ai un nouveau soucis : la requête SQL s'interrompt. Il est possible de reprendre son exécution en réenvoyant le même fichier, sauf qu'après quelques étapes, c'est MySQL qui échoue. Décidément, rien ne fonctionne !

Concentration

À ce point là, la base de donnée MySQL de mon site était vide. Mon wiki et mon blog étaient donc hors-service depuis trois heures. Autre idée pour contourner les erreurs phpMyAdmin : j'écris un script Python pour découper le dump SQL de 22 Mo en petits bouts de 8 Mo. Nouvel échec. Je tente alors 6 Mo, 5 Mo, 4 Mo : rien à faire.

Finalement, je réunis tous mes neurones pour me souvenir que j'avais déjà eu ce même soucis quelques années auparavant. Pour les gros transferts SQL, il faut utiliser la commande « mysql » (en ligne de commande via un script PHP) après avoir envoyé le dump SQL par FTP. J'upload le dump et je lance la commande: ça marche !

Merde alors, si j'avais une meilleure mémoire, j'aurai gagné 4h :-( « Quand on n'a pas de tête, on a des jambes pour courir »

Migration à MediaWiki 1.10

Après de nombreuses heures, j'avais réussi à corriger ma boulette, mais mon soucis de taille de la base MySQL persistait. Entre temps, j'étais tombé sur l'article Help:Reduce size of the database de l'encyclopédie dédiée à Star Trek. En suivant les liens, j'ai vu que le problème est ancien et corrigé : il existe un script « maintenance/deleteOldRevisions.php » pour faire le ménage. Je récupère le script pour MediaWiki 1.6 par subversion et je le lance : erreur PHP (appel à une fonction non déclarée). Je comprend que ma version de MediaWiki est trop ancienne, il faut migrer à la nouvelle version.

Je prend mon courrage à deux mains et décide de migrer MediaWiki en version 1.10. C'est toujours une bonne idée niveau sécurité. Je récupère la base de donnée de mon wiki et l'installe dans un MediaWiki 1.10 neuf. Je lance le script « php upgrade.php --quick » (lu dans la documentation MediaWiki) et à mon grand étonnement, c'est un succès au premier essai !

Réduction de la base MediaWiki

Je peux enfin lancer « php maintenance/deleteOldRevisions.php --delete ». La commande dure longtemps, une dizaine de minutes, mais s'est terminée correctement.

Je renvoie ma base de donnée mise à jour et j'installe MediaWiki 1.10 sur haypocalc.com. Tout baigne.

Conclusion

Ce qu'il faut retenir : Pensez à faire des sauvegardes et assurez vous de pouvoir l'utiliser (avant de tout casser) !

Au total, j'ai du passer environ 6h sur mon problème en transpirant tout le long à grosses gouttes. Effectivement, j'avais supprimé volontairement six ans de boulot et j'étais incapable de le restaurer.

Je doute que ce billet intéresse grand monde, mais je me devais de l'écrire pour ne pas retomber dans les mêmes pièges ;-)