Sommaire
Alors que l'année 2020 se terminait, je me suis mis à faire un petit tour des outils qui sont rentrés dans mon quotidien pendant cette période. Ça t'intéresse ? Allez, regardons ensemble.
Docker
Je ne connaissais Docker que de nom et j'avais entendu ici et là que c'était chouette pour isoler des trucs. C'est vrai que c'est chouette.
Si tu développes une application sous Linux, c'est un vrai gain d'avoir une image Docker avec toutes les dépendances de ton application. D'une part cela te permet de retrouver très facilement la liste de ses dépendances ainsi que leurs versions, d'autre part cela t'autorise à lancer des builds dans un environnement exempt de parasitage. Fini le problème du build qui tire libfoo 2.4 quand t'as besoin de la 4.2.
Sur la CI c'est bien pratique. Tu lances ton build dans une image Docker qui ne contient que ce qui est nécessaire pour compiler. Si tu oublies des dépendances, tu le vois tout de suite ; si tu mets trop de dépendances, euh…, tu ne le vois toujours pas… Si tu as un projet qui nécessite awesome-tool 2.3 et un autre qui requiert awesome-tool 3.2, tu fais une image avec chaque version et ça roule.
Après pour le cas d'un projet ayant des dépendances spécifiques, en général ça se gère aussi facilement sans Docker en configurant correctement son build et en installant les dépendances dans le build et non pas au niveau système. Mais il y a quand même quelques outils qui n'aiment pas trop être dupliqués. Par exemple Python ou Ruby. Avec Python on s'en sort un peu avec virtualenv, même si ça m'a l'air un poil fragile du fait que cela crée des liens vers le Python du système. Avec Ruby, si je me souviens bien, c'est hyper galère, voire impossible, d'avoir plusieurs installations de Ruby Version Manager. Cela dit ça fait deux ans que j'ai regardé ça, cela a peut-être changé depuis.
Néanmoins, je n'irais pas utiliser une image Docker pour le développement au quotidien. Déjà parce que ça prend une éternité de télécharger les images, ensuite parce que c'est inconfortable au possible de compiler dans l'image. À la rigueur tu peux partager ton dossier de dev pour coder sur l'hôte et compiler dans l'image, mais alors tous les fichiers deviennent la propriété de root et ça devient vite crado.
Du coup il faut quand même quelque chose d'autre pour gérer les dépendances proprement.
Enfin le plus gros problème de Docker est que ça n'existe pas sous OSX et à peine sous Windows. Quand tu cibles toutes ces plates-formes ça devient vite limitant.
Au final j'utilise volontiers Docker sur la CI pour partir d'un truc frais à chaque build, et pour pouvoir relancer d'anciens builds, mais je crois que pour ce qui est des dépendances je préfère encore utiliser quelque chose au niveau du projet.
Python
J'ai fait très peu de Python durant ma carrière ; il faut dire que j'en avait une assez mauvaise image. Déjà c'est de l'interprété, donc tu ne peux rien faire de sérieux avec, et en plus c'est lent.
Finalement c'est pas si mal.
Venant du C++ j'apprécie en particulier les facilités de formatage de chaînes de caractères, de manipulations de listes, etc. Il y a un côté concis et direct de certaines opérations qui rendent l'écriture de code assez confortable.
Venant du C++ je n'apprécie guère le duck typing et le côté interprété du langage. Lors du premier jet c'est assez agréable, le script est propre et on a tout en tête, mais lorsqu'il faut y revenir plus tard par exemple pour ajouter un paramètre à une fonction, alors ça devient galère. On se met à la recherche de tous les appelants pour les modifier, puis les appelants des appelants. Et si tu en oublies tu ne le sauras pas tant que le chemin d'exécution ne passera pas par l'appel erroné. Quelle galère.
Alors tu vas me dire, ouiiiiii, tests unitaiiiiiiires, gna gna gna, ça oblige les devs à bien couvrir leur code. Oui, mais non. C'est quand même pénible.
De mon point de vue, un code doit être correct syntaxiquement, sémantiquement, et algorithmiquement. Les tests écrits par le développeur couvrent le dernier point. Pour les deux autres un outil peut parfaitement le faire. Valider la sémantique au niveau des tests c'est mélanger les problèmes, c'est pas très single responsibility principle.
Un truc qui me perturbe un peu en Python, c'est qu'il y a une certaine résistance à l'algorithmique — le côté négatif de la concision. Genre si t'écris une boucle for à l'ancienne, avec initialisation, condition d'arrêt et incrément, tu te sens sale. Par exemple, pour extraire les éléments d'une liste selon deux propriétés indépendantes, en Python on préférera « filtrer » deux fois la liste avec un prédicat pour chaque propriété, plutôt que de boucler une seule fois et tester les deux propriétés à chaque itération. Ce que je trouve discutable puisque le deuxième filtre va retester des éléments sélectionnés par le premier.
Enfin bon, c'est juste l'avis d'un dev C++. En dehors de ces soucis c'est franchement pas mal. J'en viens même à apprécier d'écrire mes scripts en Python plutôt qu'en Bash.
LLVM
Aaaah LLVM. Quel bel outil. C'est la base de Clang, un des meilleurs compilateurs C++ du moment. En plus de l'outil je me suis mis à travailler sur les composants de LLVM lui-même, c'est à dire l'API du langage intermédiaire.
Ces dernières années LLVM est monté à toute vitesse en popularité. Une base de code jeune et accessible, en C++ et orienté objet, ça rafraîchit. Et puis ils ont bien amélioré l'état des messages d'erreurs affichés par le compilateur par rapport à ce qu'on pouvait avoir avec GCC. Entre temps, du côté du vieux GCC, les devs se plaignaient de la complexité du code depuis des années. LLVM a offert un vent de renouveau, et tout le monde est parti vers lui, délaissant l'ancêtre qui, bien que fort de 30 années d'expérience, se voit mis au placard au profit du jeunot fraîchement sorti de l'œuf.
La grande force de LLVM c'est aussi l'ensemble des outils à disposition pour transformer et manipuler du code, notamment clang-tidy, pour vérifier certaines propriétés du code, et clang-format, pour formater le code selon certaines propriétés.
Savais-tu que LLVM était lui-même codé en C++ ? À coup sûr ça doit être hyper clean.
Argh. Et bien non, ce n'est pas hyper clean du tout. LLVM est l'incarnation du cordonnier mal chaussé. On y trouve des fichiers de dizaines de milliers de lignes de code, et de l'objet à foison, même quand ça ne colle pas du tout. Dans quel modèle objet est-il acceptable pour une instance de se downcaster ? La documentation est d'un côté excellente (cf. la référence du langage par exemple) et de l'autre côté complètement inutile (cf. une bonne vieille doc Doxygen pleine de « diagrammes de collaboration » inutiles, et qui ne fait que lister les méthodes sans expliquer l'intention).
À côté de ça on a des templates à foison et des compilations interminables. J'ai vaguement espéré contourner ça en utilisant des builds unitaires mais évidemment, entre les using namespace
au niveau global et les #define
qui ne sont jamais #undef
, ça ne fonctionne pas.
Ajoute à tout ça des fichiers de plusieurs dizaines de milliers de lignes et une structure de dépôt bien chaotique, et c'est complet.
Bref, les outils fournis par LLVM sont vraiment top mais en interne c'est très décevant.
Emscripten
Emscripten est un compilateur C ou C++ vers JavaScript basé sur LLVM qui se veut être un remplaçant direct de GCC ou Clang pour compiler à peu près n'importe quel projet vers WebAssembly.
On en est à la troisième version : la première que je ne connais pas, la deuxième nommée fastcomp qui était un fork de LLVM, et la version actuelle qui s'appuie sur la version officielle de LLVM, sans modifications supplémentaires. Ce qui est assez chouette.
J'avais déjà tenté d'utiliser Emscripten il y a 8 ans pour faire une version web d'un jeu en C++ qui utilisait la SDL, OpenGL, Boost. Je ne me souviens pas du résultat mais je pense que ça n'avait pas donné grand chose. Il y a encore la trace des galères de compilation de Boost sur StackOverflow. Il faut dire qu'associer le pénible BJam avec le tout jeune Emscripten c'était un peu chercher les problèmes.
À titre personnel, je trouve que combiner du C et du JavaScript c'est un peu unir deux mondes complètement opposés ; et en dehors du fun de la technique j'ai quelques doutes sur l'utilité de l'outil. Ça permet de mon point de vue de ne pas avoir la performance du natif tout en n'ayant pas la simplicité de JavaScript, et en ne bénéficiant ni les outils développeurs du natif, ni de ceux du navigateur.
J'ai pu retoucher un peu à Emscripten récemment et j'ai découvert au passage l'existence de WASI, qui offre notamment un moyen de lancer les programmes WebAssembly en dehors du navigateur. Et là, franchement, l'idée de pouvoir écrire mon programme en C++, le compiler en WebAssembly, l'intégrer à une app Electron, installée via Flatpak, pour ensuite la lancer dans un Docker qui tourne dans une VM… Toutes ces indirections, ça me fait rêver.
Allez allez, j'arrête de blaguer là dessus.
Donc, j'ai refait un peu de WebAssembly pour le travail, et franchement c'est assez accessible. Effectivement ça remplace assez simplement un autre compilateur, et il y a de plus de nombreux points de customisation. On peut facilement, par exemple, remplacer la version de LLVM utilisée en back-end par une autre version. Facilement avec quelques limites quand même car Emscripten utilise des options de compilation en dur, qui doivent être comprises par le compilateur.
Pour ce qui est de la conversion C++ vers WebAssembly, on peut quasiment tout convertir tant qu'il n'y a pas de threads, pas d'exceptions, et autres subtilités.
Au final, il y a un truc que j'ai adoré en utilisant Emscripten, c'est l'accueil des développeurs. J'ai envoyé quelques petits patchs et ouvert quelques rapports de bug, et à chaque fois les retours étaient clairs, encourageants et constructifs. Un projet qui prend soin des nouveaux arrivants comme ça, fraaaaaaaanchement. C'est top.
C'est tout
Ces quatre projets sont les plus gros que j'ai découvert cette année. Peut-être que mon jugement est un peu à côté de la plaque ? Il faut dire que, de fait, je n'ai pas beaucoup d'expérience sur chacun.
Si tu en sais plus ou si tu vois des points remarquables à côté desquels je serai passé, n'hésite pas à me corriger dans les commentaires !
# Docker Desktop
Posté par CrEv (site web personnel) . Évalué à 8.
Mouais, c'est pas totalement vrai. Docker Desktop te fait tourner Docker sous OSX et sous Windows, où d'ailleurs tu as le choix de faire tourner des conteneurs windows ou des conteneurs linux. Les dernières versions utilisent WSL2 et ça marche quand même vachement bien.
Certains logiciels sont d'ailleurs packagés que comme des images docker, utilisables sous windows et mac genre GitPitch.
Bref, tu peux avoir un soft packagé sous forme d'une image Docker et que tu peux faire tourner sur plusieurs architectures (x86, arm, windows) ainsi que sous windows + mac à base de conteneur linux. Y compris sur les derniers mac arm.
[^] # Re: Docker Desktop
Posté par E3Ms6vyX . Évalué à 0.
La documentation sur Docker desktop semble ne pas être vraiment à jour. Dans la partie Linux / Ubuntu / Prerequisites :
- Artful 17.10 (Docker Engine (Community) 17.11 Edge and higher only)
- Xenial 16.04 (LTS)
- Trusty 14.04 (LTS)
La LTS 20.04 a presque un an. La LTS 18.04 a presque 3 ans. La LTS 16.04 ne sera plus supportée par Canonical dans quelques mois.
[^] # Re: Docker Desktop
Posté par CrEv (site web personnel) . Évalué à 5.
🤔
Ce n'est pas la doc de Docker Desktop, Docker Desktop n'est pas sous linux.
La doc d'installation de Docker sous Ubuntu est ici : https://docs.docker.com/engine/install/ubuntu/
Comment tu es tombé sur cette doc pas à jour ?
[^] # Re: Docker Desktop
Posté par CrEv (site web personnel) . Évalué à 4.
OK, cette page contient en effet des infos pas à jour.
Les infos sur ubuntu sont basées sur le temps où il y avait encore deux versions, docker-ce (community) et docker-ee (enterprise).
Désormais il n'y a plus qu'une version fournie par Docker.
[^] # Re: Docker Desktop
Posté par Julien Jorge (site web personnel) . Évalué à 2.
Je ne connaissait pas Docker Desktop, merci.
Est-ce que la version OSX permet d'avoir un conteneur OSX ? L'idéal pour moi serait de pouvoir lancer par exemple XCode dans un conteneur, ou quelque chose dans le genre.
[^] # Re: Docker Desktop
Posté par CrEv (site web personnel) . Évalué à 5.
Nope, ça n'existe pas.
Les conteneurs (Docker, OCI) sont basés sur des fonctionnalités Linux uniquement. Les conteneurs Windows c'est autre chose, basé sur l'isolation intrinsèque à windows.
Pour mac je n'ai pas connaissance de solution équivalente. L'idéal serait que ce soit développé pas Apple, mais je n'en ai pas entendu parlé.
[^] # Re: Docker Desktop
Posté par flagos . Évalué à 4.
Dans les 2 cas, il s'agit de systèmes de VM. Sur windows, j'ai cru comprendre que c'etait pas trop mal meme si les acces disques sont pas encore au top, sur macOS, c'est nettement plus lent.
Si c'est pour utiliser tous les jours des containers docker sur ces environnements, je crois que le plus simple et plus performant reste encore d'avoir une VM linux avec Virtualbox et executer docker a partir de cette machine.
[^] # Re: Docker Desktop
Posté par CrEv (site web personnel) . Évalué à 5.
Oui et non. C'est une solution, mais de là à dire que c'est plus performant je ne pense pas.
Comme tu dis, le gros point noir c'est le partage de fichier.
Sous Windows comme sous Mac les choses s'améliorent et c'est justement ce que tu ne peux pas retrouver avec une VM sous Virtualbox ou autre.
Voir par exemple ce ticket sur la roadmap publique : https://github.com/docker/roadmap/issues/7
Certaines améliorations sont activées par défaut depuis la version 2.4.0.0 sortie fin septembre : https://docs.docker.com/docker-for-mac/release-notes/#docker-desktop-community-2400
Pour Windows il y a un certain nombre de posts sur le blog de docker sur ce sujet, par exemple https://www.docker.com/blog/new-filesharing-implementation-in-docker-desktop-windows/
Dans tous les cas, partager de nombreux fichiers entre 2 VM est toujours compliqué. Que la VM supporte les fichiers ou que ce soit la machine, le problème reste entier et tout dépend l'action qu'on fait.
C'est aussi très variable suivant les frameworks par exemple.
[^] # Re: Docker Desktop
Posté par flagos . Évalué à 3.
J'avais teste il y a un an avec des collègues sur windows et plus récemment sur macOS, c'etait pour du developpement python, et c'etait le jour et la nuit. Ca marchait nettement mieux. Par contre, je me souviens plus si les fichiers étaient montes dans la VM ou si ils faisaient parti de la VM.
Apres tant mieux si docker a bosse dessus depuis, j’étais pas au courant.
[^] # Re: Docker Desktop
Posté par CrEv (site web personnel) . Évalué à 3.
Si tous tes fichiers sont uniquement dans la VM et si tu n'édites tes fichiers que dans la VMs, alors oui forcément c'est mieux. C'est indiscutable, puisque les fichiers sont locaux.
Si tes fichiers sont dans la VM mais que tu les édites depuis l'hôte ou l'inverse, alors tu peux avoir un problème. Sauf que Docker a spécifiquement changé des choses pour l'améliorer, ce que tu ne peux pas avoir avec Virtualbox.
Mais le problème est complexe, et oui c'est un frein malheureusement.
Mitchell Hashimoto (Hashicorp) utilise le principe de la VM, éditant tous ces fichiers dans la VM directement (donc en fait sans partage de fichier) https://twitter.com/mitchellh/status/1346136404682625024
C'est un bon exemple de ce qui peut se faire.
[^] # Re: Docker Desktop
Posté par pizaninja . Évalué à 3.
Mouais…
Ça impose parfois des couches de complexité supplémentaires.
Quand on se retrouve avec un PC Windows d'entreprise, derrière un proxy http, au secours ! Ce n'est pas impossible, mais ça fait perdre beaucoup de temps en paramétrage.
J'ai fini par faire du remote sur kimsufi: VSCode en mode "remote ssh".
Ça impose une connexion permanente mais:
- ça permet de pouvoir retrouver son environnement, même en changeant de PC (PC de boulot, vieux PC perso, mac de riche)
- ça permet de résoudre le pb de bande passante (machine chez OVH)
[^] # Re: Docker Desktop
Posté par CrEv (site web personnel) . Évalué à 4.
Ça n'a pas grand chose à voir avec Docker ça. C'est la même chose quand tu as du maven, des jar, des gems, ou n'importe quel besoin totalement classique.
Le problème est ici lorsque c'est mal fait :
# docker sans être root
Posté par bipbip . Évalué à 4.
Tu peux essayer de démarrer tes container de build avec les options
De cette manière, des fichiers restent les tiens, et tu profites de la config réseau de ton linux.--user $(id -u $USER) --net host
[^] # Re: docker sans être root
Posté par CrEv (site web personnel) . Évalué à 5.
Le support de docker
rootless
vient aussi de sortir d'experimental, cf https://docs.docker.com/engine/release-notes/#rootless et https://docs.docker.com/engine/security/rootless/[^] # Re: docker sans être root
Posté par eingrossfilou . Évalué à 2.
Sur les clusters de calcul, c'est plutôt singularity qui est utilisé pour faire du docker rootless.
https://sylabs.io/docs/
Comme c'est du rootless, les mécanisme de redirection de port ne sont pas disponibles.
[^] # Re: docker sans être root
Posté par cypX . Évalué à 2.
Sinon il y a podman qui est compatible avec l'écosystème Docker et qui s’affranchit complètement du compte root.
[^] # Re: docker sans être root
Posté par ff9097 . Évalué à 0.
Pourquoi ne pas juste rebuild l'image a chaque fois ? Avec le cache c'est rapide et ça évite les soucis de droits root lorsqu'on partage un volume
# Python
Posté par flagos . Évalué à 5.
Il faut configurer ton IDE pour tourner flake8, ca t'attrape pas mal de soucis:
https://flake8.pycqa.org/en/latest/index.html#quickstart
Lapin compris. Tu aurais un exemple ?
[^] # Re: Python
Posté par Julien Jorge (site web personnel) . Évalué à 5.
En l'occurrence je pensais à un truc qui ressemble à ce qui suit. Intuitivement j'aurais écris quelque chose comme :
Mais j'ai l'impression qu'on me dirait que ce serait plus Pythonic de faire :
Cette notion de "Pythonic", on la retrouve notamment dans des réponses sur StackOverflow. Par exemple :
Et là, perso, je me dis qu'utiliser des indices dans les boucles répond au problème de l'itération depuis 1792, et n'importe quel programmeur de n'importe quel langage peut comprendre une telle boucle. Est-ce que ça vaut le coup de l'éviter ? Pour quel gain ?
[^] # Re: Python
Posté par eingrossfilou . Évalué à 5. Dernière modification le 23 février 2021 à 11:54.
La version "pythonic" tendrait plus vers ça
Je suis d'accord qu'il faut un peu changer sa façon de penser.
Note: il y a certainement une formule alambiquée pour ne passer qu'une seule fois dans
some_list
tout en restant "pythonic"[^] # Re: Python
Posté par eingrossfilou . Évalué à 4. Dernière modification le 23 février 2021 à 12:16.
Ici tu aura une idée de formules alambiquées:
https://stackoverflow.com/questions/949098/python-split-a-list-based-on-a-condition
Par contre, je te mets en garde de ne pas tomber dans le travers des gens qui font du python: passer son temps à trouver une manière plus élégant d'écrire 2 lignes de code sans rien gagner à côté
[^] # Re: Python
Posté par THE_ALF_ . Évalué à 1.
Ah, mais si tu veux de l'alambiqué, il y a toujours moyen de s'arranger:
[^] # Re: Python
Posté par saimn . Évalué à 2.
Rien que ça c'est alambiqué, respectons les conventions pour commencer ;)
Sinon avec Numpy il y a plus simple:
[^] # Re: Python
Posté par THE_ALF_ . Évalué à 1.
Le but n'étais pas de faire simple :-p
Par contre je suis surpris. J'avais sorti numpy en pensant que ce serait forcément tordu vu qu'adapté pour les tableaux numériques et pas pour le texte… je ne connaissais pas les chararray.
[^] # Re: Python
Posté par THE_ALF_ . Évalué à 4.
Du coup, si l'idée est de passer par des générateurs pour éviter de créer des listes pour les parser, il y a encore mieux:
Notez la subtile distinction.
[^] # Re: Python
Posté par Glandos . Évalué à 4.
Allez, on dégaine un iPython, c'est parti.
Sur une telle liste, moyennement grosse, les générateurs ont l'air d'aller légèrement plus vite. C'était un test rapide et sûrement pourrave.
[^] # Re: Python
Posté par ff9097 . Évalué à 1.
Si tu fais du python, c'est que les performances n'est pas ta priorité. Ça ne veut pas dire qu'il ne faut pas la prendre en compte lorsqu'on a plusieurs choix mais il vaut mieux choisir ce qui est le plus clair.
[^] # Re: Python
Posté par THE_ALF_ . Évalué à 4.
Tu risque vite de te retrouver avec des scripts inutilisables car trop lents ou trop en gourmand en mémoire si tu ne fais pas attention et fait n'importe quoi. Ceci-dit, utiliser les méthodes très "pythoniques" telles que les compréhension de listes ou les générateurs plutôt que faire de grosses boucles sur les itérables doivent te permettre de gagner sur tous les tableau: ce sont des écritures assez intuitives à lire et écrire (mais différentes de ce qu'on fait en C, donc il faut s'habituer), mais qui ont été /a priori/ optimisées.
Écrire du code "pythonique" n'est pas du snobisme, c'est utiliser python tel qu'il a été pensé, et donc de manière /a priori/ optimisée. C'est dans ce sens là qu'il faut prendre l'écriture "la plus claire".
[^] # Re: Python
Posté par saimn . Évalué à 6.
En l'occurrence la version la plus rapide est la simple boucle for. Et il y a pas de mal a en utiliser une quand le besoin se justifie (liste avec pas mal d'éléments). Je vois régulièrement des gens faire des compréhension de liste (
[s for s in some_list if s.startswith('a')]
) alambiquées juste pour ne pas faire une vraie boucle for, en oubliant que le plus important est encore de privilégier la lisibilité.Sinon une autre solution pour faire une seule itération en peu moins verbeux:
[^] # Re: Python
Posté par jben . Évalué à 6.
Attention. Dans la première version, tu n'utilises pas
startswith
, et en l'occurence ici, c'eststartswith
qui est lent.Et comme cela a été dit, la manière la plus pythonique, c'est probablement de se poser la question « ai-je vraiment besoin d'une liste ? Un iterable comme un générateur ou le résultat d'un filter ne me suffirait-il pas ? »
Et c'est la limite de ce genre de truc assez stupide de construction d'objet. Construire une liste n'est pas l'objectif en soit. Et c'est un peu ce que je reproche à nombre de personnes qui font du python qui essaient de mimiquer des constructions classiques alors qu'il faudrait plutôt se poser la question avant. (Même problème dans d'autres langages, en particulier avec le C++ moderne).
[^] # Re: Python
Posté par THE_ALF_ . Évalué à 3.
Effectivement, passer par une boucle for explicite ou une compréhension de liste ne vas pas vraiment impacter la performance. Par contre, l'intérêt de la compréhension de liste est que l'on peut facilement basculer dans le monde des générateurs: il suffit de remplacer les [..] par des (..).
[^] # Re: Python
Posté par flagos . Évalué à 2.
Oui, c'est un peu la règle d'or pour avoir des performances acceptables en python: ne pas écrire de for loop et vectoriser au maximum.
[^] # Re: Python
Posté par THE_ALF_ . Évalué à 5.
Je penses que l'intérêt de cette notation est de ne générer ta liste que quand tu en a besoin, mais du coup c'est con de convertir en list tes filtres. L'idée serait plutôt de pouvoir faire ici:
Avec cette méthode, tu ne va jamais créer de liste list_a et list_b potentiellement très longue te bouffant ta mémoire. Bien entendu, cette méthode n'est pas nécessairement adaptée à toute situation, mais il s'agit une méthode très "pythonique" de gérer le problème en optimisant la mémoire.
[^] # Re: Python
Posté par El Titi . Évalué à 2. Dernière modification le 25 février 2021 à 16:51.
Avec python c'est très intuitif, mais il ne faudrait pas oublier que le générateur et l'itérateur sont des patrons de conception qui date du GoF, valables pour tous les langages OO.
Bref, l'exemple initial avec une liste vide/tableau qu'on étend (ou qu'on ne pourrait pré-allouer que si on connaissait la taille) est déjà un antipattern, y compris en C++.
[^] # Re: Python
Posté par pymaldebaran . Évalué à 5. Dernière modification le 23 février 2021 à 14:25.
Alors les index même en C++ maintenant on essaye aussi de les éviter au profit des iterateurs…
Mais le passage que tu cite :
Est vraiment très spécifique pour essayer de dire de ne pas faire des boucles sur des conteneur en utilisant les indices genre ça :
Car effectivement c'est pas pythonique et assez lent. Les boucle en python sont optimisées pour itérer sur des conteneurs ou des generateurs.
Mais ça ne veut pas dire que faire tout en fonctionnel est plus pythonique, juste qu'il faut iterer sur les élément et pas sur les index. Quand on a spécifiquement besoin de l'index (en plus de la valeur) on utilise
enumerate()
pour avoir en plus l'index. Mais c'est un peu pareil en C++11, C++14, C++17 ou C++20 car faire des boucles par iterateur évite beaucoup de soucis et peut être aussi rapide que par index. C'est juste un idiom plus récent. d'ailleurs on le voit comme idiom principale des boucles dans les langages récents comme le rust.Bon par contre quand on a appris en faisant toutes ses boucles par index c'est dur de ce le sortir de la tête.
[^] # Re: Python
Posté par groumly . Évalué à 2.
De mon point de vue c’est pas tant une question d’idiome (encore que, ça l’est un peu), mais surtout une façon d’exprimer le code façon beaucoup plus robuste et concise.
La version for loop force le lecteur à garder en tête l’input, garder un œil sur la logique d’incrémentation et traduire le if/append en semantique haut niveau.
Tu peux aussi avoir des blagues, genre modifications concurrentes sur le tableau, ou autre effet de bords qui viennent foutre la grouille.
T’es obligé de transformer en compilateur pour d’abord comprendre ce que ça fait en pratique, et c’est dur de savoir ce que le programmeur voulait faire en premier lieu.
La version « fonctionnelle » supprime le bruit, se lit beaucoup plus facilement et surtout, communique l’intention de façon beaucoup plus claire. Je peux scanner le code et immédiatement voir que la liste est filtrée 2 fois.
Ah, et ça évite (ou tout du moins, réduit considérablement) les risques d’effets de bords.
Le runtime peut aussi décider de paralléliser le code s’il le veut/peut (non pas que je connaisse un seul language qui fait ça, mais il me semble que swift travaille dessus).
En gros, la logique de 99% de ces boucles for sont du genre « pour chaque élément, applique cette opération sur l’element », ce qui n’est absolument pas ce qu’exprime une boucle for «fait tourner ce bout de code compliqué de 0 à infinité de fois ». La version fonctionnelle est beaucoup plus proche de la réalité.
Ca ouvre aussi la porte à l’évaluation paresseuse. Les streams Java typiquement font ça, tu peux construire ton stream et rien ne se passe tant que t’essayes pas de le collecter.
Mouais. On pourrait dire la même chose à propos du if/else et des jumps assembleurs. Ou du c orienté objet. Ça marche, effectivement, c’est juste que la semantique n’est pas la.
Linuxfr, le portail francais du logiciel libre et du neo nazisme.
[^] # Re: Python
Posté par THE_ALF_ . Évalué à 5.
Et pour le typage en python, il y a la solution mypy qui est assez efficace.
Effectivement, ça va un peu ralentir l'écriture du code python vu que l'on recommence à se préoccuper des types, mais d'expérience, c'est bien utile pour éviter des bugs dès qu'un projet est un peu complexe.
[^] # Re: Python
Posté par El Titi . Évalué à 2.
Et surtout, tu peux l'introduire progressivement, par exemple au moment d'écrire le TU uniquement pour valider la sémantique comme l'évoque l'auteur. Et un TU d'évité !
[^] # Re: Python
Posté par Anonyme . Évalué à 5.
En plus de flake8 et de mypy (conseillé par THE_ALF_), je conseille aussi d’utilisé black pour formater le code automatiquement. C’est l’équivalent de gofmt et ça évite les débats à rallonge sur le style.
Pour mypy, je conseille d’utiliser
--strict
qui remonte pas mal d’erreur qui peuvent être catastrophique en production.# Tu t'es fait pythonisé :)
Posté par Christophe B. (site web personnel) . Évalué à 5. Dernière modification le 23 février 2021 à 10:31.
Désolé mais tu viens de croquer la pomme :)
T'es foutu maintenant, chaque fois que tu vas vouloir écrire un script, il faudra que tu te poses la question : python / shell ou un mélange des 2 ?
Et je peu même te recommander un bon bouquin : Scripting Python Sous Linux sur le sujet ;) (enfin en partie)
[^] # Re: Tu t'es fait pythonisé :)
Posté par Glandos . Évalué à 5.
https://github.com/hauntsaninja/pyp Pour piper du shell dans du Python
https://github.com/amoffat/sh Pour appeler du shell depuis Python
Le deuxième est particulièrement efficace.
[^] # Re: Tu t'es fait pythonisé :)
Posté par Thomas Douillard . Évalué à 4.
Ou encore ipython pour intégrer du shell dans du python : https://ipython.org/ipython-doc/3/interactive/tutorial.html
Tu peux y écrire des trucs du style
fichiers = ! ls | grep .tmp
print(fichiers)
[^] # Re: Tu t'es fait pythonisé :)
Posté par Christophe B. (site web personnel) . Évalué à 3.
En fait je pensais plus a des mixtes shell + python qui sont très efficace
Exemple :
Et c'est tout après en fonction des cas de figure je modifie le fichier de log en fonction de l'historique dont j'ai besoin.
Dans l'exemple j'ai le no du jour et donc un an d'historique …
j'en ai quelques uns comme cela qui tourne depuis plus de 20 ans :)
J'ai du me servir de ce genre de chose pour la réception/emission de rapport sur des données transmises en fonction de fichier reçu/émis, rapport émis par mail.
[^] # Re: Tu t'es fait pythonisé :)
Posté par Christophe B. (site web personnel) . Évalué à 4.
le code est bizarrement affiché malgré la balise code …
c'est mieux en précisant le langage …
Désolé
[^] # Re: Tu t'es fait pythonisé :)
Posté par jben . Évalué à 6.
Si tu veux mixer le shell et le python, autant utiliser un shell qui nativement supporte le python, xonsh est vraiment génial pour cela.
[^] # Re: Tu t'es fait pythonisé :)
Posté par Christophe B. (site web personnel) . Évalué à 2.
Merci je connaissais pas …
[^] # Re: Tu t'es fait pythonisé :)
Posté par El Titi . Évalué à 2.
Ah zut doublé.
[^] # Re: Tu t'es fait pythonisé :)
Posté par El Titi . Évalué à 2.
Et après tu ne te poses même plus la question et tu ne sais même plus écrire une ligne de bash:
https://xon.sh/
# Docker, faux problèmes
Posté par damaki . Évalué à 1.
En vrai, les soucis que tu décris sur la lenteur de téléchargement des images, ça n'existe que si tu refuses de garder en local les images téléchargées. En plus tu parles du cas d'une IC, mais justement, tu vas vouloir avoir les images sous la main dans ce cas précis. Et si tu veux accélérer tes téléchargements, tu peux toujours te faire un repo proxy avec Nexus, un peu comme tu ferais un repo Debian local pour accélérer les téléchargements de paquets Debian. Bref, c'est plutôt à toi de voir selon ton usage.
À noter qu'on dit Docker par ci, docker par là, mais il y a plein d'autres outils compatibles. Par exemple, Buildah est largement plus pratique pour tous ce qui est cas d'utilisation en intégration continue. Et ça tourne en rootless.
[^] # Re: Docker, faux problèmes
Posté par CrEv (site web personnel) . Évalué à 2.
Ça m'intéresse, tu aurais des exemples concrets ?
Parce que à chaque fois que j'ai voulu regarder buildah, j'ai l'impression de revenir en arrière. Utiliser un script shell pour construire une image, ben c'est tout sauf pratique dans la majorité des cas que j'ai vu.
[^] # Re: Docker, faux problèmes
Posté par damaki . Évalué à 1. Dernière modification le 24 février 2021 à 15:14.
J'ai un example fonctionnel sous le coude, pour faire une image docker :
Il y a aussi buildah run, quand c'est pour faire un build avec une inage docker, mais je n'ai pas d'exemple. Je sais juste qu'on peut l'utiliser à peu près comme docker run
[^] # Re: Docker, faux problèmes
Posté par CrEv (site web personnel) . Évalué à 3.
J'ai du mal à voir quel est vraiment la différence avec ceci :
En quoi buildah est plus intéressant que docker ici ?
[^] # Re: Docker, faux problèmes
Posté par damaki . Évalué à 2.
Pas besoin d'avoir de droits sur le groupe docker ou équivalent, ou d'avoir accès au socket fichier du daemon docker, donc c'est nettement plus sécurisé que Docker. Ça tourne facilement même dans des chroot ou des containers, ça tourne sans daemon donc tu peux en avoir des dizaines qui tournent en parallèle sur la même machine sans impact. Pour faire le ménage, tu peux te contenter d'effacer bêtement ton $HOME/.buildah (chemin non contractuel), alors que sous docker nettoyer les déchets du build est une vraie douleur.
Bref, c'est vraiment mieux pour de l'intégration continue.
[^] # Re: Docker, faux problèmes
Posté par CrEv (site web personnel) . Évalué à 5.
ok, donc c'est uniquement à propos du côté daemonless/rootless
[^] # Re: Docker, faux problèmes
Posté par nokomprendo (site web personnel) . Évalué à 5.
ou encore nix
# LLVM
Posté par nokomprendo (site web personnel) . Évalué à 5.
C'est aussi la license BSD et les front-ends pour plein de langages
[^] # Re: LLVM
Posté par groumly . Évalué à 4.
Ainsi qu’un project lead qui est pas obsédé par saborder son propre projet pour des raisons politiques douteuses.
Linuxfr, le portail francais du logiciel libre et du neo nazisme.
# Refactoring en Python
Posté par flan (site web personnel) . Évalué à 0.
Je ne comprends pas trop ce problème, en fait : il suffit d'aller sur la fonction ou méthode à renommer, puis faire Shift-F6 (ou équivalent dans l'IDE) et choisir le nouveau nom de la méthode. L'IDE s'occupera tout seul de modifier les appels de cette méthode.
Concernant le duck-typing (ou plutôt le typage dynamique), je trouve que c'est, la majeure partie du temps, un mauvais argument.
Un IDE et un code corrects vont permettre de l'inférence de type et tu te retrouves rapidement avec les mêmes garanties de type que dans un langage typé statiquement (au moins dans l'IDE). Quand il n'est pas possible d'inférer le type, tu peux aider l'IDE avec des annotations.
Même quand je prototype, je mets les annotations nécessaires pour avoir un typage complet, par exemple.
[^] # Re: Refactoring en Python
Posté par ff9097 . Évalué à 2.
Sur une liste/dict/… où le type n'a pas été spécifié tu n'auras pas l'inférence de type. Et pareil si tu te retrouves avec une fonction qui ne retourne pas toujours le même type (on est d'accord qu'on sort du code correct).
[^] # Re: Refactoring en Python
Posté par El Titi . Évalué à 2. Dernière modification le 25 février 2021 à 17:10.
Honnêtement, même lorsque je ne l'ai pas je tape un espace après la variable, puis si je veux typer une chaine: "". et c'est parti pour la complétion
Le problème est le même pour n'importe quel langage qui comporte des collections non typées ou la généricité. any, void* même combat. Python a aussi la généricité et le cast si besoin https://mypy.readthedocs.io/en/stable/casts.html
[^] # Re: Refactoring en Python
Posté par ff9097 . Évalué à 2.
Sauf que sur les autres langages le type est toujours indiqué parce que c'est obligatoire (même si c'est Any/Object/…), en python une majeur partie de l'éco-système n'a pas (encore) été mis à jour pour l'indiquer. Après il suffit d'aller jeter un oeil au code donc c'est pas dramatique
[^] # Re: Refactoring en Python
Posté par flan (site web personnel) . Évalué à 1.
L'inférence fonctionne plutôt bien, et il est toujours possible de l'aider un peu (sans compter que PyCharm connaît les grandes bibliothèques)
# Emscripten
Posté par Zenitram (site web personnel) . Évalué à 4.
Perso ça me permet d'utiliser mon code en ligne : MediaInfoOnline.
Pas besoin de tout recoder, j'utilise le même code partout, juste à compiler avec les navigateurs comme cible + petite glue et c'est parti! C'est l'utilité de l'outil (et le C/C++ c'est vraiment un bon choix à long terme, pas à changer tous les X années de langage à la mode…)
Emscripten v2 (basé sur LLVM direct) améliore la taille, les améliorations se voient…
Emscripten, c'est bon, mangez-en!
[^] # Re: Emscripten
Posté par Julien Jorge (site web personnel) . Évalué à 4.
As-tu rencontré des soucis dans les limitations d'Emscripten concernant les threads, exceptions ou autres ?
[^] # Re: Emscripten
Posté par Zenitram (site web personnel) . Évalué à 6.
Pour un autre projet on avait des threads et ça merdait, on est passé par une autre solution plus pertinente donc on n'a pas investigué plus loin et donc on n'utilise en pratique pas les threads.
Pour les exceptions, on n'utilise pas :-p. Mais déjà entendu parlé de problème dessus, la v2.0.0 a "Store exceptions metadata in wasm memory instead of JS. This makes exception handling almost 100% thread-safe" donc peut-être qu'il y a du mieux avec la v2.
Donc les problèmes les plus connus de Emscripten ne nous posaient pas vraiment soucis.
Les plus grosses limitations vient de la sécurité elle-même des navigateurs (impossible de lire en direct les fichiers locaux, faut passer par les API des navigateurs et adapter notre propre API pour accepter des buffers plutôt que des fichiers; bref, des limitations classiques JS/navigateurs plutôt que Emscripten).
[^] # Re: Emscripten
Posté par xcomcmdr . Évalué à 3. Dernière modification le 24 février 2021 à 16:46.
Tu aurais de bons liens pour s'y mettre ?
Je voudrais convertir dune-dynasty (port open-source de Dune 2 modernisé, basé sur open-dune) dans le navigateur à l'aide de Emscripten. Oui bon pour un premier projet c'est ambitieux.
Pour le moment j'ai soit l'original, soit open-dune compilé pour DOS tournant sous WASM à l'aide du port WASM de DOSBox nommé JS-DOS 6.22.43. C'est bien mais très lourd.
Je voudrais faire pareil pour Star Control 2 UQM HD MegaMod d'ailleurs. :)
"Quand certains râlent contre systemd, d'autres s'attaquent aux vrais problèmes." (merci Sinma !)
[^] # Re: Emscripten
Posté par Zenitram (site web personnel) . Évalué à 5.
Je ne peux que conseiller la doc sur leur site, et après de la recherche sur le net quand il y a des messages d'erreur… Surtout que ce n'est pas moi qui ai mis la main de la cambouis, désolé!
Euh… Oui! Mieux de commencer petit pour apprendre…
[^] # Re: Emscripten
Posté par Julien Jorge (site web personnel) . Évalué à 4. Dernière modification le 24 février 2021 à 22:17.
Je vois que dune-dynasty se configure avec CMake, du coup pour commencer cloner le SDK d'Emscripten et lance
et puis ensuite tu peux essayer
cmake . -DCMAKE_C_COMPILER=path/to/emcc -DCMAKE_CXX_COMPILER=path/to/em++
du côté de dune-dynasty.À partir de là c'est essai/erreur :)
# je suis vieux
Posté par steph1978 . Évalué à 4.
De mon temps, Emscripten ça compilait vers asmjs…
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.