Fatigué de JavaScript - utilisez Python basé sur un navigateur

Mon expérience de développement du jeu "Snake" en Brython



image



"Attends, quoi?" - Je pense que la plupart des lecteurs réagiront au titre de cette façon.



Voulez-vous dire "utilisez simplement Python dans le navigateur"?



Tout le monde sait que seul JavaScript fonctionne dans les navigateurs.



Eh bien, ci-dessus est une capture d'écran du code source de mon site personnel. Jetez un œil, vous verrez peut-être quelque chose de nouveau pour vous-même.



Oui, c'est Python!



Maintenant, parlons de comment et comment cela fonctionne, et discutons également d'un certain nombre d'autres alternatives JavaScript.



Présentation de Brython



Brython est une implémentation JavaScript de Python3 qui vous permet d'écrire du code Python pour le Web.



Fondamentalement, il s'agit d'une bibliothèque JavaScript qui convertit votre code Python en JS équivalent et l'exécute au moment de l'exécution.



Étant donné que l'écriture de code de navigateur en Python semble cool, j'ai décidé de l'essayer.



Développement de "Snake" en Brython



image



Voici un lien vers mon site où vous pouvez essayer les versions JavaScript et Brython de Snake. Et voici un lien vers GitHub avec le code source .



Afin d'essayer Brython, j'ai décidé d'écrire le classique Snake.



Comme je ne suis ni un expert HTML Canvas ni un développeur de jeux, j'ai décidé d'utiliser cette implémentation JavaScript comme point de départ. Une fois j'ai déjà créé mon "Snake" sur la base de Canvas, mais cette implémentation est plus soignée et plus compacte.



L' auteur l'a également rédigé en moins de 5 minutes . Je dois rendre hommage à Chris DeLeon, c'est très impressionnant.



J'ai donc ajouté la notation et l'enregistrement du meilleur score à l'implémentation de Chris, et également légèrement amélioré l'interface (ajouté un bouton de pause et un bouton avec des instructions). Ensuite, j'ai porté le jeu sur Brython.



J'ai également modifié son code pour qu'il fonctionne dans un mode strict, puisque l'implémentation de Chris utilise des choses comme des variables globales implicites, qui, à mon avis, ne reflètent pas à quoi ressemble la plupart du code dans JS (je ne critique pas l'auteur - il a programmé pour le moment ). Je voulais avoir une bonne comparaison entre le code Brython et JS.



JavaScript s'est avéré être comme ça , et je ne publierai pas ce code ici, donc notre objectif est de nous concentrer sur Brython.



Bien que la majeure partie du code Brython ait été littéralement traduite à partir de JS, certaines parties (telles que la fonctionnalité de notation) ont été écrites directement en Brython puis implémentées dans JS pour voir les différences.



Le résultat final ressemble à ceci:



<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Brython Snake</title>
    <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/brython@3.8.9/brython.min.js">
    </script>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
    <style> /* Removed to keep the snippet short. Find the full file here: */ </style>
</head>

<body onload="brython()">

    <h1 class="text-center">Snake built with <a href="https://brython.info">Python!</a></h1>
    <canvas id="game-board" width="400" height="400"></canvas>
    <br>
    <h3 id="score" class="text-center">Score: 0</h3>
    <br>
    <h6 id="high-score" class="text-center">High Score: 0</h6>
    <br>
    <div class="text-center">
        <button id="instructions-btn" class="btn btn-info">Instructions</button>
    </div>

    <script type="text/python">
        
        from browser import document, html, window
        from javascript import Math
        
        score = 0
        high_score = 0

        px = py = 10
        gs = tc = 20
        ax = ay = 15
        xv = yv = 0
        trail = []
        tail = 5

        pre_pause = [0,0]
        paused = False
   
        def game():
            global px, py, tc, gs, ax, ay, trail, tail, score
            px += xv
            py += yv
            if px < 0:
                px = tc-1
            if px > tc-1:
                px = 0
            if py < 0:
                py = tc-1
            if py > tc-1:
                py = 0
            ctx.fillStyle = "black"
            ctx.fillRect(0, 0, canvas.width, canvas.height)
            ctx.fillStyle = "lime"
            for i in range(len(trail)):
                ctx.fillRect(trail[i][0]*gs, trail[i][1]*gs, gs-2, gs-2)
                if trail[i][0] == px and trail[i][1] == py:
                    score = score if paused else 0 
                    tail = 5
            trail.insert(0, [px, py])
            while len(trail) > tail:
                trail.pop()
        
            if ax == px and ay == py:
                tail += 1
                ax = Math.floor(Math.random()*tc)
                ay = Math.floor(Math.random()*tc)
                score += 1
            update_score(score)
            ctx.fillStyle = "red"
            ctx.fillRect(ax*gs, ay*gs, gs-2, gs-2)
        
        def update_score(new_score):
            global high_score
            document["score"].innerHTML = "Score: " + str(new_score)
            if new_score > high_score:
                document["high-score"].innerHTML = "High Score: " + str(new_score)
                high_score = new_score

        def key_push(evt):
            global xv, yv, pre_pause, paused
            key = evt.keyCode
            if key == 37 and not paused:
                xv = -1
                yv = 0
            elif key == 38 and not paused:
                xv = 0
                yv = -1
            elif key == 39 and not paused:
                xv = 1
                yv = 0
            elif key == 40 and not paused:
                xv = 0
                yv = 1
            elif key == 32:
                temp = [xv, yv]
                xv = pre_pause[0]
                yv = pre_pause[1]
                pre_pause = [*temp]
                paused = not paused
            
        def show_instructions(evt):
            window.alert("Use the arrow keys to move and press spacebar to pause the game.")
        
        canvas = document["game-board"]
        ctx = canvas.getContext("2d")
        document.addEventListener("keydown", key_push)
        game_loop = window.setInterval(game, 1000/15)
        instructions_btn = document["instructions-btn"]
        instructions_btn.addEventListener("click", show_instructions)
    
</script>

</body>

</html>


Donc, sur la base de cet extrait, comprenons quelques concepts de base de Brython



Connexion Brython.js



Aucune installation n'est requise pour utiliser Brython. Importez simplement le script à l'intérieur head :



<script type=”text/javascript” src=”https://cdn.jsdelivr.net/npm/brython@3.8.9/brython.min.js">


Exécuter Brython



Pour que Brython traduise et exécute le code Python comme s'il s'agissait de code JS, nous devons appeler Brythonjuste au moment du chargement du corps du document. Par exemple, comme ceci:



<body onload=”brython()”>


Cette balise recherchera les balises de scripttype "text/python"et exécutera leur code.



API pour travailler avec le Web



JavaScript par défaut donne accès aux objets comme documentet windownécessaires dans n'importe quel projet JS. En conséquence, Brython devrait également pouvoir travailler avec eux.



Pour résoudre ce problème, les créateurs de Brython pourraient simplement donner aux développeurs la possibilité d'accéder à ces objets à partir du code Python, mais cela entraînerait des cris de débogage undefined variableet une dégradation des performances.



Ainsi, pour utiliser ces API, nous devons les importer de la même manière que nous importons tout autre module Python:



from browser import document, html, window


Et vous n'avez pas besoin d'exécuter la commande pip install. Après tout, vous intégrez tout cela en HTML! Ajoutez simplement les importations requises et Brython s'occupera du reste.



Pour voir comment cela fonctionne, j'ai essayé d'utiliser plusieurs méthodes différentes de l'API Web: alert, setInterval, addEventListeneretc. Ils ont tous travaillé comme il se doit.



Objets et méthodes JavaScript intégrés



Dans Snake, dès que le serpent mange la pomme, nous devons générer une nouvelle pomme à un endroit aléatoire.



Cependant, je ne peux pas utiliser le module random de la bibliothèque Python *. Alors, comment puis-je générer un nombre aléatoire (sans écrire ma propre bibliothèque)?



Il s'est avéré que Brython a un support JavaScript plus large que je ne le pensais. Voir:



from javascript import Math
random_num = Math.floor(Math.random()*10)


Grâce au module javascript, s'il y a un objet auquel je peux accéder en utilisant JS, je peux y accéder en utilisant Brython.



Si j'importe une bibliothèque JavaScript (jQuery, Bootstrap) et que je souhaite utiliser ses méthodes, je peux le faire avec from javascript import <>. Et bien sûr, je peux également utiliser des objets JS intégrés comme Dateou String.

* Brython semble être fourni avec un certain nombre de bibliothèques Python standard implémentées directement en JavaScript, et si un module n'a pas de version JS, vous pouvez toujours l'importer. Brython obtiendra une version pure de Python et le code du module importé fonctionnera avec le code Brython. Cependant, le module aléatoire n'a pas fonctionné pour moi - mais je peux comprendre pourquoi.

Constructions spécifiques



En Python, si je veux décompresser une liste, je peux écrire list2 = [*list1]. De plus, si je veux attribuer des valeurs à une variable en fonction d'une condition, je peux écrire foo = 10 if condition else 20.



Ces constructions ont des équivalents JavaScript: l' [...arr]opérateur spread ( ) et l'opérateur ternary ( let foo = condition ? 10 : 20).



Mais Brython les prend-il en charge?



Je les ai essayés et ils ont très bien fonctionné. Vous pouvez voir que le déballage de la liste à partir de Python et l'attribution conditionnelle sont utilisés dans mon code.



Débogage



Pour être honnête, je pensais que le débogage en Brython serait horrible.



En fait, ce n'est pas si mal.



Bien sûr, j'ai écrit un projet très petit et pas très complexe, mais les erreurs générées par Brython étaient pour la plupart précises et tout à fait compréhensibles.



C'est vrai, du moins pour les erreurs de syntaxe. L'importation de modules depuis la bibliothèque Python est une histoire complètement différente.



Performance



image



JavaScript Snake



image



Brython Snake



Comme prévu, le code Brython est plus lent que JavaScript. Dans mon cas, c'était environ 1,7 fois plus lent.



Je soupçonne que dans des projets plus complexes, Brython sera plusieurs fois plus lent que le JS pur.



Cependant, vous pouvez transpiler votre code Brython à l'avance et n'utiliser que JavaScript sur la page, ce qui devrait mieux fonctionner.



En fait, j'ai essayé d'utiliser l' éditeur Brython pour convertir mon code Brython en JS et exécuter le code résultant sur une page Web, mais en raison d'un grand nombre d'erreurs, j'ai renoncé à cela pour le moment. Cependant, je n’ai pas mis trop d’efforts dans ce domaine.



Réflexions finales sur Brython



Pour être honnête, j'ai été assez impressionné par Brython. Voici quelques avantages et les inconvénients de ma propre expérience avec la langue:



Plus



  • J'ai réussi à écrire "Snake" sans problèmes inutiles, et l'expérience de débogage a été étonnamment positive.
  • Dans mon projet simple, Brython a interagi de manière transparente avec les objets JavaScript natifs disponibles sur la page
  • J'apprécie le fait que mon code semble plus propre en Python, et j'aime aussi pouvoir utiliser des constructions Python utiles pour écrire du code de navigateur.
  • Dans le cas de mon jeu, bien que Brython se charge plus lentement que JavaScript, l'utilisateur ne remarque pas cette différence.
  • Je suis ravi de voir Python dans le code source de mon site.


Moins



  • Brighton est nettement plus lent que le pur JS.
  • Brython JavaScript.
  • Brython
  • Brython .


En général, après avoir terminé mon premier projet en Brython, je peux dire avec confiance que je réessayerai un jour.



Cependant, je pense que Brython est maintenant plus adapté aux développeurs JavaScript familiers avec Python et fatigués de JS, qu'aux développeurs Python qui veulent faire du développement Web sans apprendre JavaScript.



Je pense qu'une compréhension de JavaScript est essentielle pour bien travailler avec Brython. Et si vous décidez de prendre le temps d'apprendre JavaScript pour faciliter l'écriture de Brython, vous pouvez simplement utiliser JavaScript.



Autres alternatives de navigateur JS



image



La raison pour laquelle j'ai choisi Brython était à cause de la plupart des options de transition Python vers JS que j'ai apprises pour la première fois, c'était la seule à se développer activement sur GitHub. La plupart des transpilateurs Python vers JavaScript que j'ai examinés n'ont pas eu de commits depuis plusieurs années.



Cependant, il existe d'autres alternatives.



Pyodide , par exemple, semble être une option intéressante. Il compile Python (avec ses bibliothèques scientifiques) en WebAssembly, ce qui lui permet de s'exécuter dans un navigateur.



WebAssembly, comme son nom l'indique, est un assembleur pour le Web. Tout comme l'assembleur sur nos ordinateurs peut servir d'intermédiaire entre les langages de haut niveau et le code machine, WebAssembly fait de même sur le web.



Ainsi, il est possible d'écrire un compilateur qui traduira Python (ou tout autre langage) en WebAssembly, lui permettant de s'exécuter dans le navigateur.



Il s'agit d'un projet ambitieux et prometteur qui conduira très probablement au fait que nous verrons de plus en plus de développement Web sans JavaScript.



Cependant, il en est encore à ses balbutiements (~ 3 ans), il faudra donc probablement un certain temps avant que JavaScript soit régulièrement remplacé par d'autres langages.



Et pendant que nous attendons, vous devrez utiliser des outils comme Brython si vous ne pouvez vraiment pas gérer JavaScript.



Mais honnêtement, c'est un bon début!



image


Apprenez-en plus sur la façon d'obtenir une profession de haut niveau à partir de zéro ou de monter en gamme en termes de compétences et de salaire en suivant les cours en ligne rémunérés de SkillFactory:











All Articles