Nederlands
  • python
  • programming
  • learning
  • sdk

Leer Python in een weekend: Van nul tot een compleet project

Hoe kunnen we snel een nieuwe programmeertaal leren? In dit artikel delen we onze weekendervaring van het leren van Python door een compleet project te bouwen.

Gao
Gao
Founder

Inleiding

Logto, als een identiteitsdienst, biedt een soepele ervaring in verschillende programmeertalen en frameworks. Dit houdt vaak in dat er Software Development Kits (SDK's) worden gemaakt. Echter, wanneer de programmeertaal buiten onze technische stack valt en ons team er niet mee bekend is, wordt het creëren van een sterke SDK een uitdaging.

Python was zo'n uitdaging voor ons. Ondanks dat we veel Python-gebruikers hebben, ontbrak ons een Python SDK, een aanhoudende zorg. Vastbesloten om dit aan te pakken, begon ik de kloof te overbruggen.

Hoewel ik jarenlange programmeerervaring heb, blijft Python relatief onbekend terrein voor mij. Terwijl ik jaren geleden kort met Python 2 had gewerkt voor eenvoudige scripts, was mijn kennis verouderd. Toch was het tijd om erin te duiken!

Dag 1: Leg de basis

Definieer het doel

Uit mijn ervaring is de meest effectieve manier om een nieuwe programmeertaal te leren, het bouwen van een compleet project. Gelukkig was ons doel duidelijk: een Logto Python SDK voor webapplicaties bouwen.

In plaats van meteen te beginnen met coderen, laten we het opsplitsen. Hier is de lijst:

  1. Maak de Logto-client voor taken zoals inloggen, uitloggen, gebruikersinformatie en tokenbeheer.
  2. Bied een tutorial en een voorbeeldproject om het gebruik van de SDK te tonen.
  3. Publiceer de SDK ergens zodat gebruikers deze eenvoudig kunnen installeren.

Het lijkt erop dat taak 1 het meeste werk heeft, dus we moeten de reikwijdte bevestigen en deze verder opsplitsen. Deze stap is cruciaal om de grenzen van het project veilig te stellen en om scope creep en over-engineering te voorkomen.

Eerder werk van ons team bespaarde me veel tijd:

  • Een SDK-conventie schetste de structuur en API-ontwerp van SDK's.
  • Bestaande SDK's voor verschillende talen gaven inzicht in patronen en mogelijke verbeteringen voor Python.

Met referentie naar deze bronnen zie ik een duidelijk beeld van wat te doen. Hoewel de details buiten de reikwijdte van dit artikel vallen, laten we verder gaan.

Stel de omgeving in

Ik gebruik een Mac, dus Python is al geïnstalleerd. Maar ik vroeg me af of er een betere manier was om de Python-versies te beheren (ik heb gehoord van de pijn van versiecompatibiliteit), net zoals nvm voor Node.js. Snel vond ik pyenv en begon direct met de installatie.

Vervolgens op de agenda: een pakket- en afhankelijkheidsbeheerder. Gewoonlijk zijn ze gekoppeld. Dus waarom niet pip (de standaard Python)? Als je naar de requirements.txt kijkt, zie je gewoon een lijst met pakketten met versies. Dit is niet genoeg voor een SDK die door andere projecten kan worden gebruikt. Bijvoorbeeld, we moeten misschien enkele pakketten toevoegen voor ontwikkeling, maar we willen ze niet in de uiteindelijke SDK opnemen. De requirements.txt is te simpel om dit aan te pakken.

Een van de voordelen wanneer je andere programmeertalen in je technische stack hebt, is dat je kunt zoeken naar het "Python-equivalent". Dus zocht ik naar "package.json Python equivalent" en vond Poetry, een uitstekende kandidaat:

  • Het werkt als een pakketbeheerder, afhankelijkheidsbeheerder en virtuele omgevingsbeheerder.
  • Het heeft een pyproject.toml bestand, vergelijkbaar met package.json in Node.js.
  • Het gebruikt een lock-bestand om precieze afhankelijkheidsversies te loggen.

Moderne CLI's omvatten vaak een init-opdracht op maat voor nieuwe projecten. Dat doet Poetry ook. Ik voerde de opdracht uit en het maakte een pyproject.toml bestand voor mij aan.

De eerste regel code

Eindelijk was het moment om code te schrijven aangebroken. Beginnen met het klassieke "Hello, World!" programma is altijd een goede keuze. Bij het leren van een programmeertaal zijn volwaardige IDE's niet altijd essentieel; een editor gesteund door een sterke gemeenschap, zoals VS Code, is volledig adequaat.

Gezien de focus van onze SDK op webapplicaties begon ik met een eenvoudige webserver met behulp van het populaire framework Flask.

Dankzij de mogelijkheden van Poetry kan Flask eenvoudig worden geïnstalleerd door poetry add flask uit te voeren. Vervolgens, volgens de officiële quickstart-gids van Flask, maakte ik een 'hello.py' bestand met de volgende code:

Het opstarten van de server via flask --app hello run en naar http://localhost:5000 navigeren in mijn browser leverde het gewenste resultaat op. Het werkte!

Als beginner haastte ik me niet om meer code te schrijven. In plaats daarvan is er voldoende informatie om van de code te ontvangen:

  • Gebruik from x import y om een module of een klasse te importeren.
  • Geen puntkomma om regels te beëindigen (oei).
  • We kunnen een nieuwe variabele definiëren door willekeurige namen in te voeren en een waarde eraan toe te wijzen.
  • Een instantie van een klasse maken zonder het new-trefwoord.
  • Python ondersteunt decorateurs, en de @app.route dient als een decorateur die een functie registreert als een route handler.
    • De retourwaarde van de functie wordt geïnterpreteerd als de response-body.
  • We kunnen een functie definiëren met behulp van het def-trefwoord.

Zoals je kunt zien, kunnen we veel leren van elke regel code als we proberen elke regel te begrijpen in plaats van "gewoon te maken dat het werkt". Ondertussen legde de officiële documentatie van Flask verder de snippet in detail uit.

Project kick-off

Nu is het tijd om het project te beginnen. Al snel definieerde ik een LogtoClient-klasse en probeerde een aantal eigenschappen en methoden toe te voegen om de taal te voelen:

Vervolgens integreer de klasse met Flask:

Het begon als een echt project aan te voelen. Maar ik voelde dat er iets ontbrak: een typesysteem.

Typesysteem

Aangezien het een SDK is, zal het opnemen van een typesysteem gebruikers helpen de API te begrijpen en de kans op fouten bij de ontwikkeling te verkleinen.

Python introduceerde type hints in versie 3.5. Het is niet zo krachtig als TypeScript, maar beter dan niets. Ik voegde een aantal type hints toe aan de LogtoClient-klasse:

Ziet er nu veel beter uit. Maar de uitdaging ontstond toen het op een complex type aankwam, zoals een object met vooraf gedefinieerde sleutels. Bijvoorbeeld, we moeten een LogtoConfig-klasse definiëren om het config-object te vertegenwoordigen:

Het ziet er oké uit, maar al snel zullen we de problemen van het coderen, decoderen en valideren van het object uit JSON onder ogen moeten zien.

Na wat onderzoek koos ik pydantic als de oplossing. Het is een gegevensvalidatiebibliotheek die werkt met type hints. Het ondersteunt diverse JSON-functionaliteiten zonder het volgen van omvangrijke boilerplate-code.

Dus kan de LogtoConfig-klasse worden herschreven als:

Het leerde mij ook over klasse-erfenis in Python door haakjes toe te voegen na de klassennaam.

Asynchrone operaties

Binnen de Logto SDK moeten we HTTP-verzoeken doen naar de Logto-server. Als je ervaring hebt met JavaScript, klinkt de uitdrukking "callback hell" waarschijnlijk bekend in de oren. Het is een algemeen probleem bij het omgaan met asynchrone operaties. Moderne programmeertalen presenteren vergelijkbare oplossingen zoals Promise of coroutine.

Gelukkig heeft Python een ingebouwde oplossing van async en await. Voordat je ze gebruikt, zorg ervoor dat de compatibiliteit met populaire frameworks gewaarborgd is. In Flask kan dit worden gedaan door de async extra te installeren en async def in plaats van def te gebruiken:

Dan kunnen we await gebruiken om te wachten op het resultaat van een asynchrone operatie.

HTTP-verzoeken

HTTP-verzoeken zijn een interessant onderwerp. Bijna elke programmeertaal heeft een native oplossing, maar ontwikkelaars gebruiken meestal een derdepartijbibliotheek vanwege het gebruiksgemak. Enkele voorbeelden:

  • JavaScript: XMLHttpRequest vs. fetch vs. axios
  • Swift: URLSession vs. Alamofire
  • Java: HttpURLConnection vs. OkHttp

Dit geldt ook voor Python. Mijn beslissing was om aiohttp te gebruiken omdat het async en await ondersteunt, in combinatie met zijn populariteit.

De magische Copilot

Voor Copilot zouden we nu komen tot het eentonige deel van het schrijven van businesslogica. Met behulp van de SDK-conventie en andere SDK's, kan ik de beschrijvende opmerkingen voor elke methode schrijven voordat ik de code schrijf.

Het verhoogt de leesbaarheid van de code en helpt ook ontwikkelaars de API te begrijpen direct in de IDE of editor via code-intelligentie.

Neem bijvoorbeeld de generateCodeChallenge-methode, de opmerkingen kunnen als volgt worden geschreven:

Dit stelde een geweldige prompt voor Groottaalmachines (LLMs): Methode-definities omvatten door duidelijke opmerkingen. En Copilot stelde niet teleur:

Misschien zijn er wat aanpassingen nodig, maar dat doet er niet toe. Het heeft het spel al veranderd.

Afronding

Dat is zo'n beetje de voortgang die op de eerste dag is bereikt. Het was een lange dag, maar met moderne tools en technologieën was het veel beter dan verwacht.

Dag 2: Verhoog de lat

Gebaseerd op het werk van de eerste dag was de businesslogica snel gedaan. Maar voor een SDK is het nog steeds onvoldoende. Hier zijn de taken voor de tweede dag:

  • Voeg eenheidstoetsen toe.
  • Handhaaf code-opmaak.
  • Controleer Python-versiecompatibiliteit.
  • Voeg continue integratie toe.
  • Publiceer de SDK.

Eenheidstoetsen

Eenheidstoetsen hebben ons vaak gered, dus ik zal het niet overslaan. Hier zijn algemene overwegingen bij het schrijven van eenheidstoetsen:

  • Hoe organiseer en voer je de toetsen uit?
  • Hoe stel je het resultaat vast?
  • Hoe voer je asynchrone toetsen uit? (Het klinkt als vanzelfsprekend, maar het kan af en toe problemen opleveren in sommige talen.)
  • Hoe kunnen afhankelijkheden worden gemockt? (Niet in dit onderwerp duiken totdat het onmisbaar is, want het kan naar konijnenholen leiden.)
  • Hoe genereer je code-dekking rapporten?

Met deze vragen in gedachten vond ik dat het ingebouwde unittest-module in sommige gevallen tekort schoot. Dus koos ik pytest als testframework. Het ondersteunt asynchrone toetsen en ziet er volwassen genoeg uit.

De reis onthulde enkele interessante nieuwe concepten zoals fixture aan mij. Dit kan ook de denkwijze ten goede komen bij het schrijven van code in andere talen.

Code-opmaak

Elke taal heeft zijn eigen code-opmaakstijlen. Persoonlijk kan consistente opmaak me gelukkig en comfortabel maken; het is ook nuttig voor codebeoordeling en samenwerking.

In plaats van de discussie over de "beste" stijl te volgen, besloot ik een opinionated formatter te kiezen en eraan vast te houden.

Black lijkt een goede keuze. Het enige nadeel is de onmodificeerbare tabmaat. Maar het is geen groot probleem, ik koos ervoor om het te accommoderen.

Python-versiecompatibiliteit

Als een SDK moet het compatibel zijn met gangbare Python-versies. Door te zoeken naar "python versiegebruik statistieken", besloot ik om Python 3.8 als de minimumversie te gebruiken.

De deugd van de omgevingbeheerder laat zich nu zien. Ik kan gemakkelijk de Python-versie wijzigen door pyenv local 3.8 en poetry env use 3.8 uit te voeren. Vervolgens kan ik de toetsen uitvoeren om compatibiliteitsproblemen aan het licht te brengen.

Continue integratie

Continue integratie garandeert de kwaliteit van elke code-aanpassing. Aangezien onze repository op GitHub was gehost, bood GitHub Actions de natuurlijke keuze.

De kernworkflow volgt eenvoudige principes:

  • Stel de omgeving in.
  • Installeer afhankelijkheden.
  • Bouw het project (niet nodig voor Python overigens).
  • Voer de toetsen uit.

GitHub Actions heeft een goede gemeenschap, dus het duurt slechts een paar minuten om de workflow samen te stellen.

Door matrixstrategieën te gebruiken, kunnen we de workflow op verschillende Python-versies uitvoeren, zelfs op verschillende besturingssystemen.

Publiceer de SDK

De laatste stap is om de SDK te publiceren. Voor publieke pakketten kan dit meestal worden gedaan door ze in te dienen bij het officiële taal specifieke pakkettenregister. Bijvoorbeeld, npm voor Node.js, PyPI voor Python, en CocoaPods voor Swift.

Poetry is mijn richtsnoer. Voer gewoon poetry publish uit om het pakket naar PyPI te publiceren. Zo simpel is het.

Afsluitende gedachten

Het was een boeiende reis. Zonder de hulp van de opensource gemeenschap zou het veel moeilijker zijn geweest. Applaus voor alle bijdragers!

Hier zijn enkele algemene lessen:

  • Definieer nauwkeurig het doel en splits het op, en houd het doel altijd in gedachten.
  • Stel een stabiele en reproduceerbare ontwikkelingsomgeving in.
  • Gebruik (goede) tools zoveel mogelijk.
  • Geef prioriteit aan ingebouwde of bestaande oplossingen.
  • Begrijp taalconventies en elke regel code die je schrijft.
    • Fixeer echter niet op details.
  • Gebruik Copilot voor duidelijke, beschrijvende taken.

Je kunt het uiteindelijke resultaat vinden in deze repository. Met dezelfde strategie bouwde ik ook snel de Logto PHP SDK. Aarzel niet om ons te laten weten als je suggesties hebt.

Ik hoop dat dit artikel nuttig is voor het leren van een nieuwe programmeertaal. Fijn hacken!