PROJET AUTOBLOG


Sam & Max: Python, Django, Git et du cul

Site original : Sam & Max: Python, Django, Git et du cul

⇐ retour index

Mise à jour

Mise à jour de la base de données, veuillez patienter...

Les enums en Python 1

dimanche 17 janvier 2016 à 20:01

Je n’ai jamais eu besoin d’un type exactement comme les d’Enum en Python de ma vie. Jamais eu le cas d’utilisation. Alors quand la feature est arrivé en python 3.4, cela a été un non-évènement pour moi.

Pourquoi faire ?

Je comprends parfaitement que des langages comme le C ou le Java en aient besoin. Leur syntaxe amène à ce genre de chose. Leur typage aussi. Mais Python ? Il y a tellement de manières de représenter les données, de les manipuler, de les passer.

Les enums c’étaient vraiment pour la déco à mes yeux.

Mais la fonctionnalité a fait débat. Si, si, on peut devenir tout rouge à propos d’une séquence de constantes.

Regardons un peu plus près de quoi il est question.

L’ancien statuquo

D’abord, en Python, on définit généralement les constantes ainsi :

FOO = 1
BAR = 2 DOH = 3
OYO = 4

Ce ne sont pas vraiment des constantes. Il n’y a rien qui ne puisse être réassigné en Python, même si parfois ça demande un peu de bidouillage, mais c’est une convention que les gens respectent.

Comme les modules sont des singleton, on peut facilement faire:

import module print(module.FOO)

Parfois on a besoin d’un peu plus. On veut plusieurs groupes de constantes. Alors on peut utiliser une classe.

class Stuff:     FOO = 1     BAR = 2     DOH = 3
OYO = 4

Et on peut faire:

from module import Stuff print(Stuff.FOO)

Après, il y a toujours les variantes des gens qui veulent itérer dessus.

from module import Stuff for attr, value in Stuff.__dict__.items():     print(attr, value)

Et puis il y a les gens qui veulent itérer dessus de manière ordonnée. On leur conseille généralement d’utiliser namedtuple:

from collections import namedtuple
Stuff = namedtuple('Stuff', 'FOO BAR DOH OYO')(*range(1, 5)) for val in Stuff:     print(val)

Mais certains vont vouloir les noms avec les valeurs. Ils se tourneront peut être vers OrderedDict:

from collections import OrderedDict
Stuff = OrderedDict((('FOO', 1), ('BAR', 2), ('DOH', 3), ('OYO', 4))) for attr, value in Stuff.items():     print(attr, value)

Mais pas d’accès direct par attribut, et il faut faire gaffe à la saisie ou quand on change les valeurs, etc.

Bref, les quelques personnes qui voulaient les enums n’étaient parfaitement satisfaites de ces solutions.

Ce que font les enums en Python

En gros, les Enums sont des classes bridées qui représentent des itérables de constantes. Chaque constante est un couple clé/valeur.

from enum import Enum
 
class Stuff(Enum):     FOO = 1     BAR = 2     DOH = 3     OYO = 4
 
for member in Stuff:      print(member.name, member.value)

Les enums peuvent être héritées (mais de manière limitée) et implémenter un peu de logique puisque ce sont finalement des classes.

Il existe un type IntEnum pour que chaque membre soit comparable à un int directement plutôt que de voir chercher .value, qui par ailleurs peut être n’importe quel type avec Enum.

Et on a une syntaxe raccourcie:

Stuff = Enum('Stuff', 'FOO BAR DOH OYO')

Bref, la feature ne fait pas grand-chose, en tout cas rien de ce qu’on ne pouvait faire avant. Mais elle a quelques avantages :

Mais tout ce temps après avoir vu les enums introduites, je n’en ai toujours pas l’usage. Jamais assez de constantes, ou alors quand j’en ai, je peux en faire des tuples ou des dicos sans avoir besoin d’un import.

Je suppose que je fais pas assez d’extensions C.

Quoiqu’il en soit généralement quand je vois des gens demander des enums, ce sont souvent pour de mauvaises raisons, pour reproduire ce qu’ils ont l’habitude d’utiliser dans un autre langage. Mais il y a vraiment peu de use cases typiquement Python pour les enums.

Allez, si vous avez quelques flags à mettre quelque part ou une API à wrapper, mettre une enum ne fera pas de mal.

Passer son compte linux en superuser postgres

vendredi 15 janvier 2016 à 16:27

Dans la config par défaut, les roles postgres matchent les utilisateurs système sous Linux. Au départ, le seul super utilisateur est “postgres”, et à chaque fois qu’on veut lancer psql pour faire de l’admin il faut se connecter avec ce user.

Pour se simplifier la vie en dev:

# on se log come "postgres"
sudo -i -u postgres # sous les debian likes. sinon "su" marche aussi
# on créé un utilisateur
createuser --interactive # et on dit "oui" quand il demande de créer un super user
# on créé une db à son nom
createdb ton_username

Et voilà, on peut utiliser psql depuis son compte.

Mon prompt bash est tout cassé ! 5   Recently updated !

jeudi 14 janvier 2016 à 10:43

Ça m’était déjà arrivé plusieurs fois après avoir ajouté mon env virtuel et ma branch git dans mon prompt : soudainement il se met à faire n’importe quoi. Des mixes de caractères, des sauts de ligne qui se font pas, la fusion de la ligne de commande sur elle-même.

Inutilisable.

Aujourd’hui plutôt que de subir le problème, j’ai cherché une solution, et pouf : quand on utilise des couleurs dans son prompt, il faut entourer tout le balisage de [].

Mais le balisage qui colore le prompt est composé de séquences d’échappements, qui contiennent aussi [], donc il faut mettre des anti-slash.

Du coup on passe de ça :

export PS1="\[\033[01;34m\]\$(basename '$VIRTUAL_ENV')\e[0m $PS1"

à :

export PS1="\[\033[01;34m\]\$(basename '$VIRTUAL_ENV')[\e[0m] $PS1"

à la solution qui marche :

export PS1="\[\033[01;34m\]\$(basename '$VIRTUAL_ENV')\[\e[0m\] $PS1"

Évidemment à appliquer à tous les codes d’échappement chelou qu’on a réparti un peu partout.

J’ai un tampon prêt à tirer pour le premier qui me parle de zsh.

En Python, les threads et l’asyncio s’utilisent ensemble 2   Recently updated !

mercredi 13 janvier 2016 à 13:11

En Python, les threads et l’asyncio s’utilisent ensemble

Je vois beaucoup dans les tutos ici et là des gens qui opposent asyncio avec l’ancienne manière de faire de l’IO non bloquante : les threads.

C’est une erreur : les deux méthodes ne sont pas opposées, elles sont complémentaires.

Faire des requêtes pendant que ça bloque

En effet, asyncio ne peut être non bloquant que sur le réseau : ça ne gère pas l’IO sur les fichiers. Par ailleurs, toute opération CPU bloque également la boucle d’évènement.

C’est très bien de ne pas bloquer sur le réseau, mais encore faut-il pouvoir faire la requête réseau.

Si votre programme est bloqué à attendre une compression zip qui dure 3 secondes, pendant ce temps, les opérations réseaux déjà lancées tournent bien.

MAIS IL N’EN LANCERA PAS DE NOUVELLES.

Pendant 3 secondes, aucune nouvelle requête ne sera faite puisque le programme ne fait qu’une chose : ziper. Ca marche pour d’autres choses hein : copie de fichier, gros calcul matheux, traverser une grande liste, etc.

Donc si vous avez fini toutes vos requêtes à la seconde 1, pendant 2 secondes, votre programme n’est pas utilisé à son plein potentiel.

Les threads ne permettent pas d’avancer plus vite, mais ils permettent de faire 2 travaux en parallèle. Par exemple, de lancer pendant ces 2 secondes des requêtes supplémentaires sur le réseau.

Asyncio a de l’overhead

On a vendu asyncio comme plus léger que les threads. Ce n’est pas tout à fait exact. asyncio a les avantages suivants :

Mais si on a quelques threads, le changement de contexte entre les threads est moins important que ce que coûte asyncio à faire tourner.

Pour certains travaux où le coût d’une opération réseau est faible, mais que cumulativement toutes les opérations ralentissent votre programme, un thread sera plus performant.

Par exemple, beaucoup d’opérations sur les bases de données tombent dans cette catégorie, à moins d’avoir des très longues requêtes.

Dans ce cas, avoir un thread dédié aux opérations de la base de données peut être une bonne décision.

Quoi faire ?

Si vous avez des opérations sur des fichiers ou de grosses opérations CPU, les faire travailler dans un thread peut booster votre programme. Ca tombe bien il y a une lib pour ça.

Si vous avez beaucoup de petites opérations réseau, les grouper, dans un thread à part, peut booster votre programme.

Et asyncio pour le reste, par exemple des requêtes HTTPs, DNS, SMTP, FTP, SSH, etc.

On peut donc copieusement utiliser les deux en parallèle. La bonne nouvelle, c’est que Guido a designé asyncio pour ça:

import asyncio
from concurrent.futures import ThreadPoolExecutor
 
async def main(loop, executor):
 
    # ça c’est fait avec asyncio
    await aiohttp.get('http://bidule.com')
 
    # ça c’est fait dans un thread
    await loop.run_in_executor(None, gros_calcul, params)
 
loop = asyncio.get_event_loop()
loop.run_until_complete(main(loop))

Notez bien :

Bien entendu, chaque fois que vous ajoutez un mécanisme de concurrence, vous ajoutez de la complexité, donc ne le faites que si c’est nécessaire.

Commencez avec un programme synchrone simple. Si c’est trop lent, ajouter les threads ou l’asyncio, si ça ne suffit pas, utilisez les deux.

La communauté JS est actuellement une machine à créer de la dette technique 38   Recently updated !

mardi 12 janvier 2016 à 13:45

Vous savez, quand on ne brule pas un Troll, ses blessures se soignent rapidement, et il attaque à nouveau.

Et vous savez également comme j’aime troller JS.

De plus, il y a quelque temps, je vous affirmais que NodeJS n’était pas mature.

Est-ce que l’écosystème JS a muri depuis ?

Et bien maintenant je crois qu’on a passé l’enfance, et qu’on est dans la phase de l’adolescence. Ca cri, ça bouge, ça a plein d’énergie, et ça mérite des baffes.

Je sais, je sais, je vais encore avoir une horde de fans boys qui aiment le typage mou et les champs de moustaches venir me dire que je devrais arrêter d’écrire, de coder et m’enfoncer la version imprimée de Wikipédia dans l’anus.

According to this, you're a hérétic

Comment on appelle l’adulation de quelque chose par une communauté en dépit de toute rationalité déjà ?

Mais dans l’histoire de JS, y a pas eu un moment qui ne méritait pas un bon article de ce genre. A croire que c’est volontaire.

En l’occurrence, j’ai eu envie d’écrire cet article à la suite de plusieurs évènements successifs:

Homme se servant du whisky

Laissez-moi reprendre un peu de force pour la suite

Donc, reprenons.

NodeJS est toujours splitté entre 3 versions : Node, Io.JS et convergence.

Il y a plus de frameworks front end que jamais : Angular, React, Amber, Backbone, Polymer, ExtJS, Aurelia, Durandal, Knockout, Mithril, MarionetteJS, Vue.js, Meteor, etc. Et je ne liste que les plus connus, car la liste est interminable.

Ils ont tous des versions différentes, des addons (qui ont des versions et des dépendances), des docs et tutos répartis un peu partout..

Par dessus ça, on rajoute les langages qui compilent vers du JS qui eux aussi se multiplient comme les gremlins mouillés: Coffeescript, Dart, GWT, Closure, Haxe, Elm, TypeScript, Brython, Skulpt, PyJS, etc. Vous voulez, un listing complet ? Attention ça pique les yeux.

En clair, la seule chose que les gens aiment autant que de pallier l’absence de library standard de JS est de pallier la syntaxe de JS.

The 5 steps of software development

A cela s’ajoute le problème que visiblement les devs JS et le reste du monde n’en sont pas à la même phase. Ils en sont toujours au déni.

Mais on ne peut pas blâmer uniquement le langage. La communauté JS a pris la modularité tellement à l’extrême qu’aucune solution standard ne s’est démarquée pour rien : outils de build, libs de tests, solutions de routing, toolings fonctionnels, et même packages managers…

Même à l’intérieur d’un écosystème, c’est les poupées russes. Par exemple React peut être accompagné d’un pattern que Facebook appelle Flux. C’est du MVC monodirectionnel. Les modèles sont immutables. Le contrôleur est à base d’évènements. Les vues sont gérées par des widgets React. Rien de fou, mais ça faisait pas assez innovant alors ils ont inventé un nouveau nom.

Bref, ils ont leur propre implémentation, mais même la référence n’a pas gagné la guerre. Non, en JS, ça a déclenché immédiatement un concours de celui qui pisse le plus loin et vous pouvez (devez ?) choisir entre : Flux, redux, alt, reflux, flummox, fluxible, fluxxor, marty.js, fynx, MacFly, DeLorean.js, fluxify, fluxury, exim, fluxtore, Redx, fluxx. Les noms ne sont pas une tentative d’humour de ma part.

Ce qui donne les comments du genre :

What a wonderful example of the paradox of choice!

No wonder that it’s easier to get started with Meteor + React, than with Flux + React.

Pour rappel, Meteor est le truc le plus expérimental qui existe en termes de stack techno à l’heure actuelle.

Évidemment tous ces projets ont une documentation succincte, une durée de vie aléatoire, et on peut déjà lire des trucs comme :

Flummox 4.0 will likely be the last major release. Use Redux instead.

The future starts now

Ton projet

Et ils ne sont pas compatibles entre eux. Et en fait ils ne font pas exactement la même chose :

how does redux “replace” flummox, exactly? Seems like they have two very different approaches

Je vous mets les comments car je sais que vous n’avez pas le temps d’aller lire, et encore moins d’étudier chacun de ses projets pour décider duquel utiliser, déjà qu’il faut apprendre React… A vous ne saviez pas ce qu’était React ? Mais vous êtes à la bourre dites donc !

Rassurez-vous, choisir ce genre de techno a seulement un impact sur tout le code front de votre projet. C’est tout.

Mais les outils s’améliorent, et JS est de plus en plus facile à coder. Pas vrai ? Pas vrai ?

On a créé un robot qui adore jour du piano, et on lui a mis des moufles

L’avancée technique ne veut pas forcément dire que la vie est plus belle

Nope.

React fait ramer misérablement la console de debug de Firefox.

Les préprocesseurs ont tout envahi, et si vous choisissez 4 libs, l’un sera en ES6, l’autre en typescript et la troisième en Dart. Et il faut un setup de connard pour debug du code de préprocesseur confortablement : détecteur de changement, builder, injecteur de code, source mapper…

Les frameworks comme Angular ou React ont une gestion d’erreur bien à eux, qui affichent des messages chelous.

Homme transpercé au torax par un tuyau

Pourquoi ça marche pas ? Ben…

L’installation est devenue un enfer. Entre les dépendances dépréciées, les libs incompatibles, les différents outils de build, et les options de config et les plugins, c’est une merde incommensurable. Plusieurs standards d’installeurs (et outils joints) se tirent la bourre : AMD, CommonJS et Harmony. Vous vous souvenez du temps ou on copiait juste jQuery dans le répertoire static ?

Attendez, avec Webassembly on pourra même plus faire “read source”.

Donc JS…

On peut faire plus de choses qu’avant. De manière plus propre (enfin propre, on parle de JS là…).

Mais l’écosystème, c’est le bordel général, l’anarchie totale, et ça continue d’avancer, en laissant tout le reste derrière.

Les projets JS s’accumulent, de freelances en SS2I qui se pointent, codent ou (surtout) recodent, et repartent en laissant un projet qu’il sera imbuvable à reprendre, déprécié avant même d’être terminé, non documenté, non testé.

Un projet jetable.

Judge dread regarde bruler

Ca vallait le coup de quitter PHP

Error happened! 0 - count(): Argument #1 ($value) must be of type Countable|array, null given In: /var/www/ecirtam.net/autoblogs/autoblogs/autoblog.php:428 http://ecirtam.net/autoblogs/autoblogs/sametmaxcom_a844ada43a979e3b1395ab9acb6afafb84340999/?55 #0 /var/www/ecirtam.net/autoblogs/autoblogs/autoblog.php(999): VroumVroum_Blog->update() #1 /var/www/ecirtam.net/autoblogs/autoblogs/sametmaxcom_a844ada43a979e3b1395ab9acb6afafb84340999/index.php(1): require_once('...') #2 {main}