Python-like n’a aucun intérêt 17


On voit passer des technos ici et là qui annoncent “un langage qui a un goût de Python”, “une syntaxe Python like”, “un preprocesseur qui converti un code compatible Python en JS”, etc.

Ça n’a aucun intérêt.

Oui, la syntaxe de Python fait parti de ses points forts, d’une des raisons qu’on aime le langage. Mais la syntaxe n’est PAS le langage.

Python, c’est un standard qui signifie que mon code Python tourne sur CPython, Pypy, IronPython et Jython. Ce n’est pas qu’une syntaxe. C’est aussi l’accès à une gigantesque stdlib, à des milliers de paquet sur pypi, à de la métaprogrammation, à la capacité de créer des threads, du multiprocessing, des coroutines, d’accéder au système de fichier, d’attaquer une base de données, de traiter les dates, etc.

Ce n’est pas juste la possibilité de faire :

[x * 2 for x in iterable if condition]

Au passage, généralement les Python-like, ne font même pas ça correctement. Oubliant qu’en python on peut faire aussi :

[x * 2 for x in iterable][2:6:3]
(x * 2 for x in iterable)
next(x * 2 for x in iterable)
next((x * 2 for x in iterable), 0)
{x * 2 for x in iterable}
{x: x * 2 for x in iterable}
[x + y for x, y in iterable]
[y * 2 for x in iterable for y in x]

Bref, un truc qui fait vaguement comme Python n’est pas intéressant. Si je veux quelque chose de différent, je vais utiliser un autre langage. Si je veux Python, je vais utiliser Python. Pas un ersatz qui ne me donnera pas un dixième du potentiel d’un outil que je maîtrise très bien.

17 thoughts on “Python-like n’a aucun intérêt

  • George

    (Troll inside)

    Python n’aura que peu d’intérêt aussi longtemps qu’il n’existera aucune implémentation multi-OS qui permette de packager et de redistribuer simplement des applications.

  • foxmask

    Je fais du Jython (à dose soporiphique) @ work qui me permet de déployer des applications jEE en 5min contre une heure si je devais passer par la console WebSphere … ca n’a pas “aucun interet” dans mon cas :)

  • Bouhkan

    @foxmask, je pense que Sam voulait parler de techno du genre Brython qui te permet d’utiliser la syntax python pour faire du JS (enfin je pense).

    Il cite d’ailleur le jython dans les technos liées à python.

    Python, c’est un standard qui signifie que mon code Python tourne sur CPython, Pypy, IronPython et Jython.

  • desfrenes

    ça me rappelle le coffeescript… on a fait un petit projet avec, pour tester. C’était présenté par des enthousiastes comme comparable au python mais au final même si dans l’apparence ça pouvait y ressembler, dans l’esprit c’était pas trop ça avec certains détails de syntaxe peu lisibles, voir parfois de l’ambiguité.

  • foxmask

    @bouhkan : chuis un boulet ; vais chercher un autre cafe ; merci :D

  • Seb

    About Brython : Et si… Et si ce n’était qu’une étape vers la démocratisation de Python comme langage de script dans les browsers, ou plus généralement la démocratisation de n’importe quel langage comme langage de script, et donc la disparition à terme de JS (qui serait un grand malheur pour Sam vu son AMOOOOUR inconsidéré pour le JS) ?

    Je ne connaissais pas Brython, mais ça a l’air de faire très bien le job et toutes les listes/dico/générateur en intention que tu décris sont bien gérés par l’implémentation. Après oui, le module os est une coquille vide, mais dans un contexte web, faire des opérations sur l’os… Bof bof.

  • Sam Post author

    @Seb: le problème des projets comme brython c’est qu’ils ne sont compatibles qu’en surface. Ils donnent “un gout” de Python, mais ce n’est pas python.

    On ne peut pas utiliser la plupart des libs de pypi avec, ce qui réduit à néant l’interêt du truc.

    On ne peut pas utiliser PDB (faut utiliser le debugger du nav, avec un source map en plus et donc toute la chaine d’installation qui va avec).

    On ne peut pas utiliser les layers de compatibilités 2/3. Donc si tu as un code qui marche sur 2 et 3, ça marche pas avec brython :

    >>> from __future__ import unicode_literals
    Traceback (most recent call last):
      module __main__23 line 116
        _ = editor_ns['_'] = eval(currentLine, editor_ns)
      module __main__23 line 131
        exec(currentLine, editor_ns)
      module exec_70 line 1
        from __future__ import unicode_literals
    ImportError: cannot import __future__

    Les metaclasses ne marchent pas. Dis au revoir aux ORM et tous les outils avec une API un peu sympas :

    def prefixer(name, bases, dct):
        nouveaux_attributs = {}
        for nom, val in dct.items():
            if not nom.startswith('__'):
                nouveaux_attributs['attaque_' + nom] = val
            else:
                nouveaux_attributs[nom] = val
     
        # On délègue la création de la classe à type() :
        return type(name, bases, nouveaux_attributs)
     
    class Essai(metaclass=prefixer):
        def test(self):
            print('yolo')

    Python est un langage TRES propre. Cela fait parti de ses grandes qualités. Il y une spec, des PEPs, et on sait à chaque version ce qui se passe. On peut faire confiance à Python.

    Quelle confiance peut on accorder à brython ? Pas grand chose. La doc dit que Python 3 est supporté, mais difficile de savoir quelle version. Or je note que :

    >>> import sys
    >>> sys.version
    '3.3.0 (default, 2015-03-27 08:50:51.466000) \\n[Javascript 1.5] on Brython'

    Donc on peut imaginer que c’est du 3.3. Or, le mot clé yield et return sont supportés. Mais depuis la 3.3 return et yield peuvent se retrouver dans le corps d’une fonction.

    Sauf que non :

      module exec_70 line 3
        return 1
               ^
    SyntaxError: 'return' with argument inside generator

    Et tout est comme ça. Des milliers de petits détails qui n’ont pas l’air important, mais qui, groupés, rendent Brython inutilisable pour autre chose que des cas simples et casse la compatibilité avec tous les outils existant.

    Je suis 100% pour voir Python remplacer Javascript. Si c’est Python.

    Mais ce n’est pas Python. Derrière on tourne sur une VM JS. Et donc il y a une event loop qui tourne et d’ailleurs brython l’expose. Du coup, ce qu’on peut attendre du comportement du langage change complètement. Ce n’est plus le même langage.

    Ce n’est pas Python embarqué dans le nav, c’est une surcouche qui maquille avec une syntax Python un moteur JS.

    Autant faire du JS : on travaille directement avec l’outil le plus adapté à la situation.

    J’entends déjà les gens dire : “ouai, mais moi je vais que du JS simple, c’est surtout pour me simplifier la vie”. Sauf que non. C’est un préprocesseur : vous devez le compiler vers JS, donc soit le client prend la pénalité de perf, soit vous devez ajouter des étapes de builds et de debug en plus dans votre dev.

    Et tout ça pour quel gain ? Avoir une syntaxe un peu plus jolie ? Python ce n’est pas une syntaxe bordel !

    Même pour les trucs simples, Brython marche pas. Un truc super chiant, c’est l’impossibilité de générer un hash ou un uuid en JS sans avoir un installer une lib. Est-ce que Brython aide ? Nan !

    >>> import uuid
    module uuid not found
    >>> import hashlib
    >>> hashlib.md5("fdjsklm")
     
    Internal Javascript error: TypeErrorAttributeError: 'Exception' object has no attribute 'args'
    Traceback (most recent call last):
      module __main__23 line 116
        _ = editor_ns['_'] = eval(currentLine, editor_ns)
      module __main__23 line 131
        exec(currentLine, editor_ns)
      module __main__23 line 116
        _ = editor_ns['_'] = eval(currentLine, editor_ns)
      module __main__23 line 116
        _ = editor_ns['_'] = eval(currentLine, editor_ns)
      module __main__23 line 116
        _ = editor_ns['_'] = eval(currentLine, editor_ns)
      module __main__23 line 116
        _ = editor_ns['_'] = eval(currentLine, editor_ns)
      module __main__23 line 116
        _ = editor_ns['_'] = eval(currentLine, editor_ns)
      module __main__23 line 116
        _ = editor_ns['_'] = eval(currentLine, editor_ns)
      module __main__23 line 116
        _ = editor_ns['_'] = eval(currentLine, editor_ns)
      module __main__23 line 151
        _ = exec(block_src, editor_ns)
      module __main__23 line 155
        traceback.print_exc()
      module __main__23 line 116
        _ = editor_ns['_'] = eval(currentLine, editor_ns)
      module __main__23 line 151
        _ = exec(block_src, editor_ns)
      module __main__23 line 116
        _ = editor_ns['_'] = eval(currentLine, editor_ns)
      module __main__23 line 131
        exec(currentLine, editor_ns)
      module __main__23 line 116
        _ = editor_ns['_'] = eval(currentLine, editor_ns)
      module __main__23 line 116
        _ = editor_ns['_'] = eval(currentLine, editor_ns)
      module __main__23 line 151
        _ = exec(block_src, editor_ns)
      module __main__23 line 116
        _ = editor_ns['_'] = eval(currentLine, editor_ns)
      module __main__23 line 116
        _ = editor_ns['_'] = eval(currentLine, editor_ns)
      module __main__23 line 151
        _ = exec(block_src, editor_ns)
      module __main__23 line 116
        _ = editor_ns['_'] = eval(currentLine, editor_ns)
      module __main__23 line 116
        _ = editor_ns['_'] = eval(currentLine, editor_ns)
      module __main__23 line 116
        _ = editor_ns['_'] = eval(currentLine, editor_ns)
      module __main__23 line 151
        _ = exec(block_src, editor_ns)
      module __main__23 line 116
        _ = editor_ns['_'] = eval(currentLine, editor_ns)
      module __main__23 line 151
        _ = exec(block_src, editor_ns)
      module __main__23 line 116
        _ = editor_ns['_'] = eval(currentLine, editor_ns)
      module __main__23 line 151
        _ = exec(block_src, editor_ns)
      module __main__23 line 116
        _ = editor_ns['_'] = eval(currentLine, editor_ns)
      module __main__23 line 116
        _ = editor_ns['_'] = eval(currentLine, editor_ns)
      module __main__23 line 116
        _ = editor_ns['_'] = eval(currentLine, editor_ns)
      module __main__23 line 116
        _ = editor_ns['_'] = eval(currentLine, editor_ns)
      module __main__23 line 116
        _ = editor_ns['_'] = eval(currentLine, editor_ns)
      module __main__23 line 116
        _ = editor_ns['_'] = eval(currentLine, editor_ns)
      module __main__23 line 116
        _ = editor_ns['_'] = eval(currentLine, editor_ns)
      module __main__23 line 131
        exec(currentLine, editor_ns)
      module posix line 225
        return __BRYTHON__.brython_path # XXX fix me
      module __main__23 line 116
        _ = editor_ns['_'] = eval(currentLine, editor_ns)
      module __main__23 line 116
        _ = editor_ns['_'] = eval(currentLine, editor_ns)
      module __main__23 line 118
        print(repr(_))
      module __main__23 line 141
        traceback.print_exc()
      module traceback line 9
        if exc.args:

    Les projets comme Brython et autres sont de bonne volonté, mais au final, ils sont dangereux. Les gens qui vont commencer à les utiliser vont se retrouver avec tout un tas de contraintes, pour très peu de bénéfice.

    On peut, bien entendu, implémenter un sous ensemble de Python bien défini. A partir du moment où on le vend comme tel, où on est très clair sur les bénéfices apportés par rapport au coût, où on documente très bien ce qu’on fait et ce qu’on ne fait pas.

    RPython, Cython, Jython, MicroPython et IronPython font ça.

  • Seb

    Ok, je comprends mieux ; effectivement, je n’avais que survolé et tenté des “trucs simples” comme tu dis.

    Ta réponse mériterait presque d’être dans l’article, qui en l’état fait penser à une colère d’un pythoniste gâté (le seul exemple concret de trucs concrets qui “marchent pas” passent en effet très bien sur le premier lien donné en comms).

  • Sam Post author

    Non, les exemples donnés de l’article ne marchent exactement pareil avec brython non plus.

    On a tendance à considérer que “ça ne plante pas == ça marche”. Mais quand on veut quelque chose qui match Python, il faut avoir le comportement de Python. Et ce n’est bien entendu le cas que pour les cas simples. Comme par exemple les erreurs, c’est important qu’elles soient les mêmes.

    Python :

    next([x * 2 for x in “”], 0)

    Traceback (most recent call last):

    File ““, line 1, in

    TypeError: ‘list’ object is not an iterator

    Brython :

    next([x * 2 for x in “”], 0)

    NaN

    Mais bon, pas besoin d’aller aussi loin, il foire sur des choses aussi simples que ‘s’ * True, une veille astuce pour pluraliser les mots.

    Et je ne parle pas de l’immonde stack trace générée qui ne sert absolument à rien pour le débugging.

    Quand on utilise brython, on peut mettre 10 ans d’expérience Python à la poubelle. La syntaxe n’est PAS le langage.

  • matthieu

    Perso, j’aimerais bien avoir des syntaxes à la Python pour remplacer JS, Java et C, même sans l’écosystème.

    Beaucoup des trucs vraiment sympa de Python (le slicing, les listes/dict/set en intension, …) sont tout à fait compatibles avec un typage statique fort (comme C et Java), et permettrait de coder beaucoup plus rapidement.

  • Pierre Quentel

    Salut,

    Ici l’auteur de Brython. Je suis d’accord sur le fond : les langages intermédiaires entre Python et Javascript comme RapydScript ou PythonJS (d’ailleurs abandonné) n’ont aucune chance de succès, les développeurs Python veulent du “vrai” Python.

    L’objectif de l’équipe Brython est bien d’aller vers 100% de compatibilité avec Python, en tout cas pour tout ce qui a du sens dans un navigateur (on oublie l’écriture de fichiers). Qu’on n’y soit pas encore, c’est certain, mais au stade où on en est il faut un peu se creuser la cervelle pour trouver des exemples qui ne marchent pas (utiliser une fonction comme argument de metaclass, je n’y aurais pas pensé !).

    En tout cas quand quelque chose n’est pas compatible avec le Python Language Reference, c’est un bug. Soit on se dit “c’est de la daube”, soit on prend la peine d’aller sur le tracker et de déposer un ticket pour faire progresser le projet. A chacun de voir. De mon côté j’ai bien noté les bugs que tu signales et je vais les corriger.

  • Sam Post author

    Salut Pierre. Je te souhaites beaucoup de chance dans ton aventure, c’est un projet difficile. Je ne cherchais pas à démonter brython en particulier, mais le concept Python-like en général. Si un jour brython deviens un remplacement drop-in pour cPython, je serai le premier à en faire la promotion.

  • Arnaud Legout

    Bonjour,

    il ne faut pas non plus oublier un point très important avec ces “Python-like” comme dit Sam,

    même si certains utilisateurs n’y trouvent pas leur compte, le développeur du Python-like lui apprend énormément.

    Et c’est peut-être ça le plus important.

    Je reste personnellement toujours impressionné par ces efforts d’implémenter Python en javascript parce que, au final,

    ça montre une compétence impressionnante en Python et en javascript.

    Il faut se souvenir aussi de comment est né Python: une grande culture informatique, les mains dans le cambouis avec ABC et une frustration de ne pas pouvoir ce qu’on veut.

    J’imagine que si on prenait un peu de JIT de pypy, un peu d’expérience de Python en javascript et beaucoup de travail, on ne serait

    pas loin d’une VM python nativement dans le navigateur.

  • Sam Post author

    Ce n’est pas Python like, c’est la VM complète de CPython portée en JS. C’est intéressant, mais la taille du build rend la solution impraticable, et par ailleurs, on est toujours sur une VM JS derrière, avec tout un tas de subtilités type : event loop implicite, type numérique JS…

    Disons que l’avantage est d’avoir toute la stdlib à sa disposition, les outils d’inspection et un système d’erreur niquel. C’est donc un essai intéressant, mais toujours inutilisable.

Leave a comment

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <pre> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Des questions Python sans rapport avec l'article ? Posez-les sur IndexError.