Müde von JavaScript - verwenden Sie browserbasiertes Python

Meine Erfahrung mit der Entwicklung des Spiels "Snake" in Brython



Bild



"Warte, was?" - Ich denke, die meisten Leser werden so auf den Titel reagieren.



Meinst du "benutze einfach Python im Browser"?



Jeder weiß, dass nur JavaScript in Browsern funktioniert.



Nun, oben ist ein Screenshot des Quellcodes meiner persönlichen Website. Werfen Sie einen Blick darauf, vielleicht sehen Sie etwas Neues für sich.



Ja, es ist Python!



Lassen Sie uns nun darüber sprechen, wie und wie gut es funktioniert, und eine Reihe anderer JavaScript-Alternativen diskutieren.



Wir stellen Brython vor



Brython ist eine JavaScript-Implementierung von Python3, mit der Sie Python-Code für das Web schreiben können.



Grundsätzlich handelt es sich um eine JavaScript-Bibliothek, die Ihren Python-Code in das entsprechende JS konvertiert und zur Laufzeit ausführt.



Da das Schreiben von Browsercode in Python cool klingt, habe ich beschlossen, es auszuprobieren.



Entwicklung von "Snake" in Brython



Bild



Hier ist ein Link zu meiner Website, auf der Sie die JavaScript- und Brython-Versionen von Snake ausprobieren können. Und hier ist ein Link zu GitHub mit dem Quellcode .



Um Brython auszuprobieren, habe ich beschlossen, die klassische Schlange zu schreiben.



Da ich kein HTML Canvas-Experte oder Spieleentwickler bin, habe ich mich für diese JavaScript-Implementierung als Ausgangspunkt entschieden. Einmal habe ich meine "Schlange" bereits auf Basis von Canvas erstellt, aber diese Implementierung ist ordentlicher und kompakter.



Der Autor schrieb es auch in weniger als 5 Minuten . Ich muss Chris DeLeon Ehre machen, es ist sehr beeindruckend.



Also habe ich Chris 'Implementierung um Scoring und Speichern erweitert und auch die Benutzeroberfläche leicht verbessert (eine Pause-Schaltfläche und eine Schaltfläche mit Anweisungen hinzugefügt). Dann habe ich das Spiel nach Brython portiert.



Ich habe auch seinen Code so geändert, dass er in einem Modus funktioniert strict, da Chris 'Implementierung Dinge wie implizite globale Variablen verwendet, die meiner Meinung nach nicht widerspiegeln, wie der größte Teil des Codes in JS aussieht (ich kritisiere den Autor nicht - er hat für die Zeit programmiert ). Ich wollte einen guten Vergleich zwischen Brython und JS-Code erhalten.



JavaScript hat sich als solches herausgestellt, und ich werde diesen Code hier nicht veröffentlichen. Unser Ziel ist es, uns auf Brython zu konzentrieren.



Obwohl der größte Teil des Brython-Codes buchstäblich aus JS übersetzt wurde, wurden einige Teile (wie die Scoring-Funktionalität) direkt in Brython geschrieben und dann in JS implementiert, um die Unterschiede zu erkennen.



Das Endergebnis sieht folgendermaßen aus:



<!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>


Lassen Sie uns anhand dieses Ausschnitts einige grundlegende Brython-Konzepte verstehen



Brython.js Verbindung



Für die Verwendung von Brython ist keine Installation erforderlich. Importieren Sie einfach das Skript in head :



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


Brython laufen lassen



Damit Brython Python-Code wie JS-Code übersetzen und ausführen kann, müssen wir Brythonnur dann aufrufen, wenn der Dokumententext geladen ist. Zum Beispiel so:



<body onload=”brython()”>


Dieses Tag sucht nach Tags vom scriptTyp "text/python"und führt deren Code aus.



API für die Arbeit mit dem Web



JavaScript standardmäßig ermöglicht den Zugriff auf Objekte wie documentund windowin jedem JS Projekt benötigt. Dementsprechend sollte Brython auch mit ihnen arbeiten können.



Um dieses Problem zu lösen, könnten die Entwickler von Brython Entwicklern einfach die Möglichkeit geben, über Python-Code auf diese Objekte zuzugreifen. Dies würde jedoch zu Debugger-Schreien undefined variableund Leistungseinbußen führen.



Um diese APIs verwenden zu können, müssen wir sie wie jedes andere Python-Modul importieren:



from browser import document, html, window


Und Sie müssen den Befehl nicht ausführen pip install. Schließlich binden Sie alles in HTML ein! Fügen Sie einfach die erforderlichen Importe hinzu und Brython erledigt den Rest.



Um zu sehen , wie gut es funktioniert, habe ich versucht , das Web verschiedene Methoden der API zu verwenden: alert, setInterval, addEventListenerusw. Sie alle arbeiteten so, wie sie sollten.



Integrierte JavaScript-Objekte und -Methoden



In "Schlange" müssen wir, sobald die Schlange den Apfel frisst, an einer zufälligen Stelle einen neuen Apfel erzeugen.



Ich kann das Zufallsmodul aus der Python * -Bibliothek jedoch nicht verwenden. Wie kann ich also eine Zufallszahl generieren (ohne meine eigene Bibliothek zu schreiben)?



Es stellte sich heraus, dass Brython eine breitere JavaScript-Unterstützung bietet, als ich dachte. Sehen:



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


Dank des Moduls javascriptkann ich mit Brython auf ein Objekt zugreifen, auf das ich mit JS zugreifen kann.



Wenn ich eine JavaScript-Bibliothek (jQuery, Bootstrap) importiere und deren Methoden verwenden möchte, kann ich dies tun from javascript import <>. Und natürlich kann ich auch eingebaute JS-Objekte wie Dateoder verwenden String.

* Brython wird anscheinend mit einer Reihe von Standard-Python-Bibliotheken geliefert, die direkt in JavaScript implementiert sind. Wenn ein Modul keine JS-Version hat, können Sie es trotzdem importieren. Brython erhält eine reine Python-Version und der importierte Modulcode funktioniert neben dem Brython-Code. Das Zufallsmodul hat bei mir jedoch nicht funktioniert - aber ich kann verstehen, warum.

Spezifische Konstruktionen



Wenn ich in Python eine Liste entpacken möchte, kann ich schreiben list2 = [*list1]. Wenn ich einer Variablen basierend auf einer bestimmten Bedingung Werte zuweisen möchte, kann ich auch schreiben foo = 10 if condition else 20.



Diese Konstrukte haben JavaScript-Entsprechungen: den [...arr]Operator "pread ( let foo = condition ? 10 : 20) " und den Operator" ternary ( ) ".



Aber unterstützt Brython sie?



Ich habe sie ausprobiert und sie haben großartig funktioniert. Sie können sehen, dass in meinem Code Listen-Unboxing aus Python und bedingte Zuweisung verwendet werden.



Debuggen



Um ehrlich zu sein, dachte ich, das Debuggen in Brython wäre schrecklich.



Eigentlich ist es nicht so schlimm.



Natürlich habe ich ein sehr kleines und nicht sehr komplexes Projekt geschrieben, aber die von Brython geworfenen Fehler waren größtenteils genau und ziemlich verständlich.



Dies gilt zumindest für Syntaxfehler. Das Importieren von Modulen aus der Python-Bibliothek ist eine ganz andere Geschichte.



Performance



Bild



JavaScript-Schlange



Bild



Brython-Schlange



Wie erwartet ist Brython-Code langsamer als JavaScript. In meinem Fall war es ungefähr 1,7 mal langsamer.



Ich vermute, dass Brython in komplexeren Projekten um ein Vielfaches langsamer sein wird als reines JS.



Sie können Ihren Brython-Code jedoch im Voraus transpilieren und nur JavaScript auf der Seite verwenden, um eine bessere Leistung zu erzielen.



Ich habe versucht, den Brython-Editor zu verwenden, um meinen Brython-Code in JS zu konvertieren und den resultierenden Code auf einer Webseite auszuführen, aber aufgrund einer großen Anzahl von Fehlern habe ich dies vorerst aufgegeben. Ich habe mir jedoch nicht allzu viel Mühe gegeben.



Letzte Gedanken zu Brython



Um ehrlich zu sein, war ich ziemlich beeindruckt von Brython. Hier sind einige Vor- und Nachteile aus meiner eigenen Erfahrung mit der Sprache:



Vorteile



  • Ich habe es geschafft, "Snake" ohne unnötigen Aufwand zu schreiben, und die Debugging-Erfahrung war überraschend positiv.
  • In meinem einfachen Projekt interagierte Brython nahtlos mit den auf der Seite verfügbaren nativen JavaScript-Objekten
  • Ich schätze die Tatsache, dass mein Code in Python sauberer aussieht, und ich finde es auch toll, dass ich nützliche Python-Konstrukte verwenden kann, um Browsercode zu schreiben.
  • Bei meinem Spiel wird Brython zwar langsamer als JavaScript geladen, der Benutzer bemerkt diesen Unterschied jedoch nicht.
  • Ich freue mich, Python im Quellcode meiner Site zu sehen.


Minuspunkte



  • Brighton ist deutlich langsamer als reines JS.
  • Brython JavaScript.
  • Brython
  • Brython .


Nachdem ich mein erstes Projekt in Brython abgeschlossen habe, kann ich zuversichtlich sagen, dass ich es eines Tages erneut versuchen werde.



Ich glaube jedoch, dass Brython jetzt eher für JavaScript-Entwickler geeignet ist, die mit Python vertraut sind und JS satt haben, als für Python-Entwickler, die Webentwicklung durchführen möchten, ohne JavaScript zu lernen.



Ich denke, ein Verständnis von JavaScript ist wichtig, um gut mit Brython zusammenzuarbeiten. Und wenn Sie sich die Zeit nehmen, JavaScript zu lernen, um das Schreiben in Brython zu vereinfachen, können Sie einfach JavaScript verwenden.



Andere Browser-JS-Alternativen



Bild



Der Grund, warum ich mich für Brython entschieden habe, war, dass die meisten Python-zu-JS-Migrationsoptionen, die ich zum ersten Mal kennengelernt habe, die einzige waren, die sich aktiv auf GitHub entwickelte. Die meisten Python-zu-JavaScript-Transpiler, die ich mir angesehen habe, hatten seit mehreren Jahren keine Commits mehr.



Es gibt jedoch andere Alternativen.



Pyodid zum Beispiel scheint eine interessante Option zu sein. Es kompiliert Python (zusammen mit seinen wissenschaftlichen Bibliotheken) zu WebAssembly, wodurch es in einem Browser ausgeführt werden kann.



WebAssembly ist, wie der Name schon sagt, ein Assembler für das Web. So wie Assembler auf unseren Computern als Vermittler zwischen Hochsprachen und Maschinencode fungieren kann, tut WebAssembly dies auch im Web.



Auf diese Weise ist es möglich, einen Compiler zu schreiben, der Python (oder eine andere Sprache) in WebAssembly übersetzt und im Browser ausgeführt werden kann.



Dies ist ein ehrgeiziges und vielversprechendes Projekt, das höchstwahrscheinlich dazu führen wird, dass wir ohne JavaScript immer mehr Webentwicklungen sehen werden.



Es steckt jedoch noch in den Kinderschuhen (~ 3 Jahre), daher wird es wahrscheinlich einige Zeit dauern, bis JavaScript regelmäßig durch andere Sprachen ersetzt wird.



Und während wir warten, müssen Sie Tools wie Brython verwenden, wenn Sie wirklich nicht mit JavaScript umgehen können.



Aber ehrlich gesagt ist dies ein guter Anfang!



Bild


Erfahren Sie mehr darüber, wie Sie einen hochkarätigen Beruf von Grund auf neu aufbauen oder Ihre Fähigkeiten und Ihr Gehalt verbessern können, indem Sie an den kostenpflichtigen Online-Kursen von SkillFactory teilnehmen:











All Articles