Site original : Sam & Max: Python, Django, Git et du cul
Dans un langage fortement typé comme Python, on ne peut pas additionner des choux et des carottes, comme disait madame Germaine, ma prof de mate.
Par exemple on ne peut pas faire ça :
>>> 1 + "1" Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unsupported operand type(s) for +: 'int' and 'str'
Nonnnnnnnn !
Ni ça :
>>> [1] + (1,) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: can only concatenate list (not "tuple") to list
Pas biennnnnnnnnnnnnn !
Et pas ça :
>>> True + 1 2
OUATE ZE PHOQUE ?
Pendant longtemps, Python n’a pas eu de type bool, et on utilisait, comme en C, 0 pour faux, et 1 pour vrai. Ça marchait pas mal, mais dans un souci de rentre le langage plus propre, on a voulu créer une type spécialisé, et ainsi :
>>> type(True) <class 'bool'> >>> type(1) <class 'int'>
Mais il faut avouer que pouvoir interchanger True pour 1 et False pour 0 et vice versouille, c’était achement pratique dans une discipline ou la manipulation des chiffres à des fins logiques est un peu la base du métier. Du coup il a été décidé que les booléen seraient des travs, juste une surcouche au dessus des entiers, et qu’on pourrait les utiliser en lieu et place de ceux-ci. Une exception étonnante vu la rigueur du langage sur la gestion des types.
Du coup :
>>> True == 1 True >>> False == 0 True >>> True + 1 2 >>> False - 1 -1
Par contre :
>>> 1 is 1 True >>> True is True True >>> True is 1 False
Donc voici quelques moyens de détourner l’utilisation des booléens pour écrire du Perlthon…
On peut utiliser un bool pour de l’indexing ou du slicing :
>>> ('Valeur 1', 'Valeur 2')[True] 'Valeur 2' >>> list(range(10)[True:False-1:2]) [1, 3, 5, 7]
On peut utiliser un bool pour multiplier, et l’opération multiplier marche sur les strings et les listes…
>>> "J'aime les chat" + "s" * est_pluriel "J'aime les chat" >>> est_pluriel = True >>> "J'aime les chat" + "s" * est_pluriel "J'aime les chats" >>> def process(lst, cancel=False): ... lst = list(lst) * (not cancel) ... for i in lst: ... print(i) ... >>> process(range(3)) 0 1 2 >>> process(range(3), True)
Ou même pire, saviez-vous que la déclaration d’héritage et les clauses d’exception pouvaient inclure une expression ? En rajoutant de l’unpacking, on obtient un truc bien marrant :
>>> class Parent: ... foo = "bar" ... >>> inherit = False >>> class Enfant(*[Parent] * inherit): ... pass ... >>> Enfant().foo Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: 'Enfant' object has no attribute 'foo' >>> inherit = True >>> class Enfant(*[Parent] * inherit): ... pass ... >>> Enfant().foo 'bar' >>> catch = True >>> try: ... 42 / 0 ... except (ZeroDivisionError,) * catch: ... print("Nope") Nope >>> catch = False >>> try: ... 42 / 0 ... except (ZeroDivisionError,) * catch: ... print("Nope") Traceback (most recent call last): File "<ipython-input-12-c01f7e27284d>", line 2, in <module> 42 / 0 ZeroDivisionError: division by zero
Évidelement ça marche avec n’importe quels entiers, mais où serait le fun ?
Et on peut utiliser un bool pour incrémenter une valeur.
>>> increment = True >>> value = 0 >>> for x in range(10): ... value += increment ... >>> value 10 >>> increment = False >>> for x in range(10): ... value += increment ... >>> value 10
Voilà de quoi bien vous marrer au boulot lors de votre prochaine code review !
Ceci est un post invité de Coyote posté sous licence creative common 3.0 unported.
Et oui, il fallait bien que ça arrive.
Bon, ça avait commencé doucement. Il y a de ça quelques temps (avant même l’article de Sam), j’avais configuré mon Sublimissime pour qu’il me force les import
du __futur__
.
Étant moi-même un peu un nazi de la convention de code, ça ne m’a pas dérangé plus que cela: les keyword print
et autres sont pas trop ma tasse de thé. Par contre, c’est vrai que ça m’a un peu forcé la main sur les import relatifs, que j’utilisais visiblement un peu trop.
Récemment, sur un autre projet, je me dis “allez, je passe à la syntaxe "hello {}".format("world")
au lieu des "hello" % "world"
” puisque c’est ce qui est désormais recommandé. Bon, c’est un peu chiant au début mais on s’y fait vite.
Aussi, j’ai adopté la suppression des prefix u devant les strings. Je sais qu’avec Python 3.3 on peut à nouveau les utiliser, mais vraiment, j’ai toujours trouvé ça moche et insupportable, alors je suis très content de ne plus avoir à me les farcir.
Que ceux que je vois râler me disent comment ils justifient qu’avec ce temple de la simplicité et de la lisibilité qu’est Python, on doivent préfixer toutes nos chaines par des petits u
ridicules.
Voilà pour l’historique, lentement mais surement, je me préparais à prendre peut-être de bonnes habitudes pour le jour (très) lointain ou Python3 deviendrait réalité.
Et c’est là que mon collègue, un pervers à lunettes, nous propose d’utiliser PY3 pour de vrai, sur un nouveau projet.
C’est vrai que le projet s’y prêtait bien: un petit site web de CRUD avec Django. On s’est gratté le menton deux minutes et puis on s’est dit “pourquoi pas ?”.
C’est con hein, mais la première chose que tu fais, c’est te demander qu’est ce qui change entre PY2 et PY3.
Et bien la réponse est pas simple du tout et si tu crois que tu vas trouver une URL avec une liste de chose à changer, tu te trompes lourdement.
Le problème est que PY3.0 avait sans doute dû être fini à la pisse et que donc les choses ont beaucoup évoluées entre 3.0, 3.1, 3.2 et 3.3. J’ai lu beaucoup de posts sans importance sur toutes ces étapes intermédiaires, mais la conclusion, c’est que grosso-modo, il faut passer de 2.7 à 3.3. Entre les deux, c’est un peu comme naitre au Sahara Occidental.
Comme on travaille en équipe, on a des setup différents: OSX, Ubuntu 12.04 et Ubuntu 13.04.
Ça c’est passé sans douleur malgré les appréhensions. Pour Ubuntu, il suffit d’utiliser le ppa deadsnakes.
Une fois installé, un coup de virtualenv (mkvirtualenv -p /usr/bin/python3.3 monenv3
) et c’est parti.
Comme expliqué plus haut, on a choisi de faire ce projet en PY3 parce qu’il est petit et sans dépendances ; donc pas très représentatif.
Cependant, on utilise:
Django==1.5.4
South==0.8.2
django-mptt==0.6.0
django-picklefield==0.3.0
numpy==1.7.1
unicodecsv*
Aucun problème avec ceux là. On a cru que South nous faisait des misères mais en fait c’était un import relatif avec un pass
de cochon qui foutait la merde (try: from local_settings import * except ImportError: pass
.
Donc la leçon ici, c’est que les imports relatifs c’est mal.
Au niveau des dépendances, on a du se séparer de batbelt. Oui, je parle bien de sametmax/Bat-Belt qui n’est pas du tout PY3 proof. Ne pleurez pas, moi aussi j’ai été très déçu et j’attends des explications (foireuses, je les vois venir d’ici).
Bref, comme on utilise batbelt pour presque rien, on a copié honteusement (ou pas) le code nécessaire.
Dernière remarque, vous voyez dans la liste unicodecsv
. C’est un peu tricky puisque PY3 supporte unicode par défaut, le module csv
de PY3 fonctionne directement ; et de fait, unicodecsv
n’existe plus. Oui, je me suis fait avoir comme un débutant.
Bref, comme on souhaite aussi supporter PY2 et pas uniquement PY3, on a un beau if PY2: import unicodecsv as csv else: import csv
.
Peu nombreux je dois dire et c’est plutôt encourageant. De tête:
__unicode__()
dans les modèles Django.implements_to_string
qui permet de ne définir que __str__()
(renvoie de l’unicode) et le reste est géré automatiquement.django.utils.encoding.python_2_unicode_compatible
mais je préfère la toolbox Jinja.unicodecsv
. Ici c’était le seul, mais clairement dans beaucoup de projet qui manipulent des stream ou des fichiers, il va falloir faire ce genre de combines pour suporter PY2 et PY3.django-picklefield
. Le field se comportait correctement avec PY3 mais pas avec PY2 et pas dans tous les cas. Du bonheur à
x = MyModel(id=1)
x.picklefield = [1,2,3]
x.save()
x = MyModel(id=2)
x.picklefield = {'a': 1, 'b': 3}
x.save()
dict.keys()
et assimilés ne renvoient plus de listes, mais ont été remplacés par leur équivalents générateurs (dict.iterkeys()
) et ceux-ci n’existent plus. Donc un peu de gymnastique syntaxique quand on est habitué à l’ancienne syntaxe.chaussette
et circus
que j’utilise pour le déploiement ne sont pas compatibles PY3 !! Pas de debug ici, ça ne s’installe même pas. Résulalt: on a déployé en PY 2.7. Bon, pour vous consoler (et moi avec), le github de ces 2 projets est plein de commits récents en rapport avec PY3 donc j’imagine que ça ne saurait tarder.Et bien, on a un petit projet développé à plusieurs, en PY3.3, qui est déployé en PY2.7 donc c’est possible ; on a pas rencontré de grande difficultées donc je pense que pour du web, c’est pas loin d’être mûr.
Pas grand chose à dire finalement, et c’est sans doute ça le plus important !
Allez bookmarker le site python3porting qui contient les infos sur ce qui a changé. Ca a l’air long mais en fait, y’a beaucoup de cas spécifiques.
Ceci est un post invité de Recher posté sous licence creative common 3.0 unported.
– Assistance informatique, bonjour.
– Salut les moines bouddhistes. Comment je fais pour aller sur Youtube ? Votre stupide filtre à puceaux me bloque l’accès !
– C’est lié à la politique de l’entreprise. Le site est totalement interdit.
– Mais bordel, c’est la pause de midi ! Je suis toute seule dans mon service, et je suis excitée ! Pas un seul stagiaire à me mettre sous la dent ! J’ai besoin de mes vidéos pornos ! Et quand je dis “besoin”, c’est VRAIMENT besoin !
– Veuillez m’excuser Madame, mais je ne peux rien pour vous.
– J’ai la patcholle qui palpite à la vitesse d’une levrette au galop ! C’est urgent !
– La patcholle ? Mais enfin Madame, ce mot n’existe même pas !
– Le mot n’existe peut-être pas, mais ma patcholle, elle, elle existe ! Et elle est pas loin de la combustion spontanée !
– La seule solution serait que vous achetiez des DVD, et que vous les rameniez à votre bureau. On ne contrôle que ce que vous faites sur internet, pas ce que vous visionnez en local.
– Merci pour le conseil, mon p’tit chou, j’ai tout ce qu’il faut à la maison. Mais là, c’est d’une vidéo spécifique dont j’ai envie. Celle avec le nain et les ballons de baudruche. Et elle n’est que sur Youtube !
– Vous pouvez la télécharger. Changez l’URL, ajoutez les lettres “ss” devant le mot “youtube”, sélectionnez ensuite la qualité parmi celles disponibles, et vous récupérerez le fichier sur votre disque. Par exemple : http://www.ssyoutube.com/watch?v=uSGnmCTkIfE. Avec un peu de chance, l’accès par la connexion de l’entreprise n’est même pas bloqué.
– Attendez j’essaye. Je connais l’adresse de ma vidéo par cœur. … Oh putain, ça marche ! Et ça passe même le filtre à puceaux de Youtube ! Ooouiiiii !! Va y avoir de la cyprine plein les murs !
– Cela m’a fait plaisir d’avoir pu vous aider, Madame.
– De même. Dites, pendant que ça télécharge, vous voulez pas venir me rendre visite ? On se trouverait bien quelques corpuscules de Krause avec lesquels s’occuper.
– Merci Madame, mais ça ne m’intéresse pas.
– Je vous propose du sexe gratuit et vous n’en voulez pas ? Ah d’accord, vous êtes homosexuel. J’aurais dû m’en douter, à votre petite voix fluette. De toutes façons, ils sont tous pédés dans l’informatique.
– Au contraire Madame, je suis hétérosexuelle. En revanche, je suis une femme. Bon après-midi à vous.
Retour à la normale, avec notre bon vieux WP pourri, un cache trop agressif devant, un design moche et des articles honteux.
Bienvenue sur Sam et Max.
Donc après que Lease Web nous ait lâché plusieurs fois dans le mois, notre Varnish a décidé de ne pas fonctionner pour une raison qui restera mystérieuse. Du coup on a pris un autre hébergeur, et Max, dans une tentative désespérée avant la migration, a tenté une cure par imposition des mains.
Ça a marché, du coup j’ai pris un serveur pour rien ^^ On va rester sur ce serveur du fait de notre flemme légendaire et parce que, bah, on a aucun revenu attaché au blog donc si il est pas disponible ça nous coûte rien à part de répondre aux tweets attristés des fans.
Bref, je reviens avec plein d’idées d’articles, des concepts novateurs (qui ne verront jamais le jour par manque de temps, mais c’est l’intention qui fait le forgeron) et quelques millions d’entrées dans les mails, flux RSS et autres outils dit “d’information” qui ont pour mission de s’assurer que vous n’aurez jamais la bonne, noyée dans la masse.
Notre référencement s’est évidement fait plomber, car un bonheur n’arrive jamais seul. Mais on s’en fout parce qu’on a encore pu profiter de la plage et du soleil pendant que vous êtes tous sous la grisaille. Et savoir que la situation des autres est pire que la sienne, ça n’a pas de prix.
C’est reparti !
Attention chérie ça a tranché !
Certains d’entre vous auront remarqué que le site était down ces derniers jours, notre hébergeur a eu des petits problèmes avec ses VPS dont nous faisions partie.
Sam&Max n’est pas mort, Sam est actuellement indisponnible jusqu’à la fin du mois et moi je suis un peu occupé en Asie, non pas que j’ai pas le temps d’écrire un article, mais pas l’envie car la tête ailleurs, j’espère que vous le comprendrez ;)
Pour ceux que ça interresse j’essaierai de vous faire un topo sur mon déménagement d’ici quelques semaines quand je serai revenu à une vitesse de croisière ^^
Bises à tous et bonnes vacances, oui nous on les prend en septembre :p