Svenska
  • python
  • programmering
  • lärande
  • sdk

Lär dig Python på en helg: Från noll till ett komplett projekt

Hur kan vi snabbt lära oss ett nytt programmeringsspråk? I den här artikeln delar vi med oss av vår helgupplevelse av att lära oss Python genom att bygga ett komplett projekt.

Gao
Gao
Founder

Introduktion

Logto, som en identitetstjänst, är det viktigt att tillhandahålla en smidig upplevelse över olika programmeringsspråk och ramverk. Detta innebär ofta att skapa Software Development Kits (SDKs). Men när programmeringsspråket ligger utanför vår teknikstack och vårt team saknar erfarenhet, blir det en utmaning att skapa ett robust SDK.

Python utgjorde en sådan utmaning för oss. Trots att vi hade många Python-användare saknade vi ett Python SDK, vilket var en kvarstående oro. Besluten att adressera detta, började jag brygga denna klyfta.

Även om jag har flera års programmeringserfarenhet, är Python fortfarande relativt outforskad mark för mig. Även om jag hade experimenterat med Python 2 kort för enkla skript för många år sedan, var min kunskap föråldrad. Ändå var det dags att dyka in!

Dag 1: Lägg grunden

Definiera målet

Av erfarenhet är det mest effektiva sättet att lära sig ett nytt programmeringsspråk att bygga ett komplett projekt. Som tur var var vårt mål klart: konstruera ett Logto Python SDK för webbapplikationer.

Istället för att hoppa direkt in i koden, låt oss bryta ner det. Här är listan:

  1. Skapa Logto-klienten för uppgifter som inloggning, utloggning, användarinfo och tokenhantering.
  2. Tillhandahålla en handledning och ett exempelprojekt som visar användningen av SDK.
  3. Publicera SDK så att användare enkelt kan installera det.

Det ser ut som uppgift 1 har mest arbete, så vi behöver bekräfta omfattningen och fortsätta bryta ner den. Detta steg är avgörande för att säkra projektets gräns och undvika omfattningsglidning och överingenjörer.

Tidigare arbete av vårt team sparade mig massor av tid:

  • En SDK-konvention beskrev strukturen och API-designen för SDK:er.
  • Befintliga SDK:er för olika språk gav insikter i mönster och potentiella förbättringar för Python.

Genom att referera till dessa resurser kan jag se en tydlig bild av vad som behöver göras. Även om specifika detaljer går utanför denna artikels omfattning, låt oss gå vidare.

Ställ in miljön

Jag använder en Mac, så Python är redan installerad. Jag undrade dock om det finns ett bättre sätt att hantera Python-versionerna (jag har hört talas om smärtan med versionens kompatibilitet), precis som nvm för Node.js. Snabbt hittade jag pyenv och började direkt installera det.

Nästa på agendan: en paketerings- och beroendemanager. Vanligtvis är de kopplade. Så varför inte pip (Python-standard)? Om du tittar på requirements.txt, kommer du märka att det bara är en lista över paket med versioner. Detta är inte tillräckligt för ett SDK som kan användas av andra projekt. Till exempel kanske vi behöver lägga till några paket för utveckling, men vi vill inte inkludera dem i det slutliga SDK:et. requirements.txt är för enkelt för att hantera detta.

En av fördelarna när du har andra programmeringsspråk i din teknikstack är att du kan söka efter "Python-ekvivalent". Så jag sökte efter "package.json Python-ekvivalent" och hittade Poetry, en strålande kandidat:

  • Det fungerar som en paketmanager, beroendehanterare och hanterare för virtuella miljöer.
  • Den har en pyproject.toml-fil, liknande package.json i Node.js.
  • Den använder en låsfil för att registrera exakta beroendeversioner.

Moderna CLI:er omfattar ofta ett init-kommando som är anpassat för nya projekt. Poetry gör det också. Jag körde kommandot och det skapade en pyproject.toml-fil åt mig.

Den första raden kod

Äntligen hade ögonblicket att skriva kod anlänt. Att börja med det klassiska "Hello, World!"-programmet är alltid ett bra val. När man lär sig ett programmeringsspråk är fullfjädrade IDE:er inte alltid nödvändiga; en redaktör backad av en stark gemenskap, såsom VS Code, är helt tillräcklig.

Med tanke på vårt SDK:s fokus på webbapplikationer började jag med en enkel webbserver som använde det populära ramverket Flask.

Genom att utnyttja Poetries kapabiliteter kan Flask enkelt installeras genom att köra poetry add flask. Sedan, enligt Flasks officiella snabbstartsguide, komponerade jag en 'hello.py'-fil med följande kodbit:

Att starta servern via flask --app hello run och navigera till http://localhost:5000 på min webbläsare resulterade i det önskade resultatet. Det fungerade!

Som nybörjare var jag inte snabb att skriva mer kod. Istället finns det mycket information att ta emot från kodbiten:

  • Använd from x import y för att importera en modul eller en klass.
  • Inga semikolon för att avsluta rader (oj då).
  • Vi kan definiera en ny variabel genom att ange ett godtyckligt namn och tilldela ett värde till det.
  • Skapa en instans av en klass utan new-nyckelordet.
  • Python stöder dekorerare, och @app.route fungerar som en dekorerare som registrerar en funktion som en routhanterare.
    • Funktionens returvärde tolkas som svarskropp.
  • Vi kan definiera en funktion genom att använda def-nyckelord.

Som du kan se, om vi försöker förstå varje rad kod istället för att "bara få det att fungera", kan vi lära oss mycket av det. Samtidigt förklarade Flasks officiella dokument ytterligare kodbiten i detalj.

Projektstart

Nu är det dags att starta projektet. Snart definierade jag en LogtoClient-klass och försökte lägga till några egenskaper och metoder för att känna språket:

Därefter integrera klassen med Flask:

Det började kännas som ett riktigt projekt. Men jag kände att något saknades: ett typeringssystem.

Typeringssystem

Eftersom det är ett SDK, kommer det att hjälpa användarna att förstå API:et och minska risken för fel vid utveckling genom att inkorporera ett typeringssystem.

Python introducerade typhintar i version 3.5. Det är inte lika kraftfullt som TypeScript, men det är bättre än ingenting. Jag la till några typhintar till LogtoClient-klassen:

Ser mycket bättre ut nu. Men utmaningen dök upp när det kommer till en komplex typ som ett objekt med fördefinierade nycklar. Till exempel, vi måste definiera en LogtoConfig-klass för att representera konfigurationsobjektet:

Det ser okej ut, men snart måste vi möta problemen med att koda, dekoda och validera objektet från JSON.

Efter lite forskning valde jag pydantic som lösning. Det är ett datavalideringsbibliotek som fungerar med typhintar. Det stödjer olika JSON-funktioner utan att följa tråkig boilerplate-kod.

Därför kan LogtoConfig-klassen skrivas om som:

Det lärde mig också om klassarv i Python genom att lägga till parenteser efter klassnamnet.

Asynkrona operationer

Inom Logto SDK, behöver vi göra HTTP-förfrågningar till Logto-servern. Om du har erfarenhet av JavaScript, klingar termen "callback hell" troligen bekant. Det är ett vanligt problem när man hanterar asynkrona operationer. Moderna programmeringsspråk presenterar liknande lösningar som Promise eller coroutine.

Lyckligtvis har Python en inbyggd lösning av async och await. Innan du använder dem, säkerställ kompatibiliteten med populära ramverk. I Flask kan detta göras genom att installera async-extra och använda async def istället för def:

Då kan vi använda await för att vänta på resultatet av en asynkron operation.

HTTP-förfrågningar

HTTP-förfrågningar är ett intressant ämne. Nästan varje programmeringsspråk har en inhemsk lösning, men utvecklare använder vanligtvis ett tredjeparts-bibliotek eftersom det är lättare att använda. Några exempel:

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

Detta är också sant för Python. Mitt beslut var att använda aiohttp eftersom det stöder async och await samt dess popularitet.

Copilot-magin

Tidigare än Copilot, skulle vi nu komma till den tråkiga delen av att skriva affärslogik. Med hjälp av SDK-konventionen och andra SDK:er kunde jag skriva de beskrivande kommentarerna för varje metod innan jag skrev koden.

Det ökar kodens läsbarhet och hjälper utvecklare att förstå API:et direkt i IDE eller redaktör via kodintelligens.

Till exempel, överväg generateCodeChallenge-metoden, kommentarerna kan skrivas som:

Detta utgjorde ett bra prompt för stora språksmodeller (LLMs): sammansättning av metoddefinitioner genom tydliga kommentarer. Och Copilot gjorde inte besviken:

Några justeringar kan behövas, men det spelar ingen roll. Det har redan förändrat spelet.

Avrundning

Det är ungefär framstegen som uppnåddes under den första dagen. Det var en lång dag, men med moderna verktyg och teknologier var det mycket bättre än jag förväntat mig.

Dag 2: Höj ribban

Baserat på arbetet den första dagen blev affärslogiken snabbt färdig. Men för ett SDK är det fortfarande otillräckligt. Här är uppgifterna för den andra dagen:

  • Lägg till enhetstester.
  • Tvinga fram kodformatering.
  • Verifiera kompatibilitet med Python-version.
  • Lägg till kontinuerlig integration.
  • Publicera SDK.

Enhetstester

Enhetstester har räddat oss många gånger, så jag kommer inte att hoppa över det. Här är vanliga överväganden när man skriver enhetstester:

  • Hur organiserar och kör man testerna?
  • Hur bekräftar man resultatet?
  • Hur kör man asynkrona tester? (Det låter självklart men det kan ibland orsaka problem i vissa språk.)
  • Hur mockar man beroenden? (Dyk inte in i detta ämne förrän det är oumbärligt, eftersom det kan leda in i en kaninhål.)
  • Hur genererar man kodtäckningsrapporter?

Med dessa frågor i åtanke fann jag att det inbyggda unittest-modulen inte räckte för vissa fall. Så jag valde pytest som testramverk. Det stöder asynkrona tester och ser tillräckligt moget ut.

Resan avslöjade några intressanta nya koncept som fixture för mig. Detta kan också gynna tankesättet när man skriver kod i andra språk.

Kodformatering

Varje språk har sina egna kodformateringsstilar. Personligen kan konsekvent formatering göra mig glad och bekväm; det är också hjälpsamt för kodgranskning och samarbete.

Istället för att bläddra i argumentet för den "bästa" stilen, bestämde jag mig för att välja en bestämd formatterare och hålla mig till den.

Black ser ut som ett bra val. Den enda frustrationen är den omodifierbara flikstorleken, men det är inget stort problem, jag valde att anpassa mig till det.

Python versionskompatibilitet

Som ett SDK bör det vara kompatibelt med rådande Python-versioner. Genom att söka efter "python version usage statistics", bestämde jag att använda Python 3.8 som minsta version.

Fördelarna med miljöhanterare visar sig nu. Jag kan enkelt växla Python-versionen genom att köra pyenv local 3.8 och poetry env use 3.8. Då kunde jag köra testerna för att avslöja kompatibilitetsproblem.

Kontinuerlig integration

Kontinuerlig integration garanterar kvaliteten på varje kodändring. Eftersom vårt arkiv fanns på GitHub presenterade GitHub Actions det naturliga valet.

Kärnworkflowen följer enkla principer:

  • Ställ in miljön.
  • Installera beroenden.
  • Bygg projektet (Inte nödvändigt för Python dock).
  • Kör testerna.

GitHub Actions har ett bra community, så det tar bara några minuter att konstruera workflowen.

Genom att använda matrisstrategier kan vi köra workflowen på olika Python versioner, även på olika operativsystem.

Publicera SDK

Det sista steget är att publicera SDK. För offentliga paket kan detta vanligtvis göras genom att skicka till det officiella språksspecifika pakethanteringsregistret. Till exempel, npm för Node.js, PyPI för Python, och CocoaPods för Swift.

Poetry är min ledstjärna. Kör bara poetry publish för att publicera paketet till PyPI. Det är så enkelt.

Avslutande tankar

Det var en engagerande resa. Utan hjälp från öppen källkodscommunity hade det varit mycket svårare. Beröm till alla bidragsgivare!

Här är några allmänna lärdomar:

  • Definiera målet exakt och bryt ner det, håll sedan alltid målet i åtanke.
  • Sätt upp en stabil och reproducerbar utvecklingsmiljö.
  • Använd (bra) verktyg så mycket som möjligt.
  • Prioritera inbyggda eller befintliga lösningar.
  • Förstå språkets konventioner och varje kodrad du skriver.
    • Men fokusera inte på småsaker.
  • Använd Copilot för tydliga, beskrivande uppgifter.

Du kan hitta det slutgiltiga resultatet i detta arkiv. Med samma strategi byggde jag också snabbt Logto PHP SDK. Tveka inte att låta oss veta om du har några förslag.

Hoppas den här artikeln är hjälpsam för att lära sig ett nytt programmeringsspråk. Lycka till med hackandet!