Uke 48
Denne uken jobbet vi med:
- Vi snakket om hvordan maskiner kommuniserer (HTTP Metoder / Responser, 404/403/418/200, GET/POST) 🕸
- Vi logget inn på https://rapidapi.com/hub med vår GitHub konto 💻
- Vi testet ulike APIer ved å velge
Python -> Requests
metoden 🐍 - Vi lærte å navigere i JSON objekter i Python 📊
- Vi lærte litt om lister og dictionaries
- Vi så på hvordan vi kan lage et uendelighetsprogram gjennom en
while
loop/løkke ➰
Fun fact om API - Discord Bots!
APIer brukes overalt! På Discord for eksempel, kan du motta en API nøkkel for å logge på en chatterobot gjennom Discords egen API; https://discord.com/developers/applications.
Ja, det kreves litt lesing, forkunnskaper, feilsøking og prøving - men det er ikke umulig å få til!
Her vil man finne funksjoner i Python som lar deg lese meldinger eller discord handlinger, samt sende meldinger tilbake, gjennom Python!
Se https://realpython.com/how-to-make-a-discord-bot-python/ for mer informasjon!
Ikke viktig å få med seg alt
Når vi lærer å kode, så vil det nesten være umulig å forstå alt med en gang, dette er vanlig!
Det blir dessverre mange løse tråder, vår jobb er å vite littegrann om dem, slik at vi vet om mulighetene, uten å nødvendigvis forstå dem helt. Vi trenger å vite søkeord - “request weather data from api” er mye bedre søkeord enn “get weather python”, selv om det helt sikkert fungerer.
Vær derfor ikke bekymret om ikke alt faller naturlig på plass i hodet, selv de beste må google de enkleste ting og lære seg dem på ny en gang i blant.
Onsdags kode
På onsdag så vi på API‘er på siden RapidAPI. API betyr Application Programming Interface, og er en metode for å kommunisere med en applikasjon via programmering. For eksempel i spillet Minecraft kan man referere til “blokker” via ulike metoder som objekter i programmering, da det er grensesnittet utviklerne har laget.
API kan virke som et litt stort hopp fra forrige uker, læringskurven kan være stor, men mulighetene er enda større, teksten under er derfor litt lang.
Vi så først på YR sin utviklerportal, hvor det står mye informasjon om hvordan man kan hente data-vennlig informasjon, men dette er ikke “nybegynner” vennlig: https://developer.yr.no/doc/GettingStarted/. RapidAPI er en mye enklere plattform for å benytte seg av APIer.
I eksempelet brukte vi Covid-19 APIet: https://rapidapi.com/api-sports/api/covid-193/. Merk at man er nødt til å abonnere på API‘er for å motta en Token / Nøkkel, som er tilsvarende brukernavn og passord for å kunne benytte seg av tjenesten. Dersom prisen er på $0.00, behøver man ikke å taste inn betalingsinfo. Velg derfor Subscribe for å få en gyldig X-RapidAPI-Key
.
På fanen Endpoints
får man ulike metoder å interagere med tjenesten, som vil variere fra ulike API‘er. GET betyr at en henter informasjon, mens POST betyr at en sender. På fanen Example Responses
vil man se hva slags informasjon de ulike endpointene inneholder. I Covid-19 tjenesten mottar man informasjon som antall nye tilfeller, antall smittede, antall tester, dato for oppdatert statistikk samt litt informasjon om landet (innbyggere, kontinent, etc.).
Når man har valgt Endpoints får man velge ulike parametre å gi til tjenesten på midten av siden. Dette er viktig, ettersom dette er parametre vi kan endre gjennom kode, for eksempel å velge land gjennom et brukergrensesnitt/chatterobot. For eksempel dersom man benytter seg av en vær-varsel API, vil det (nok) være ønskelig å kunne skrive inn ønsket by man vil sjekke været i.
Tjenesten generer automatisk en Code Snippet
basert på programmeringsspråk. Standard er satt til Node.js - Axios
, som er standard for webutvikling. Vi skal bruke Python, med Requests
som metode.
PyCharm
Opprett en ny fil som du navngir api.py
, her kan du kopiere og lime inn code-snippeten. Vi skal gjøre noen modifikasjoner.
Installer Requests pakken
Dersom du får en rød strek under import requests
, betyr det at pakken requests
ikke er installert. Som regel kan du høyreklikke på feilmeldingen, og velge Install missing package
. Alternativt kan du åpne fanen Python Packages
og søke etter requests
, og installere den fra der.
Eventuelt må du åpne et konsollvindu/terminal, og skrive inn følgende:
Øverst i filen plasserer man imports
, annen kode som kommer fra andre steder. Her må vi importere requests
, som i snippeten.
I snippeten er det generert kode for oss, men skal kun brukes for å teste endpointet. Vi ønsker å konvertere den til en funksjon, der vi har mer kontroll over bruken:
- Endpointet, hvor dataen kommer fra
- Vår “query”, hva kan vi spørre tjeneren om? Her kan vi velge
country
ogday
- X-RapidAPI-Key er vårt brukernavn OG passord, denne får vi av RapidAPI når vi abonnerer på API‘et. Uten denne får vi ingen tilgang.
- Her lagrer vi resultatet vi får gjennom å kjøre
requests.request
funksjonen,GET
er metode for innhenting,url
er sted,headers
inneholder vår token (innlogging / autentikasjon),params
er de ulike parametrene vi har lov til å redigere. - Standard for å teste, skriver ut hele resultatet vi får fra serveren som tekst.
Dersom vi nå bruker funksjonen min_funksjon()
, vil koden kjøre som normalt, og vi vil få resultatet printet til konsollen i tekst (print(response.text)
). Dette er nyttig for å teste ut, men vi ønsker som regel å gjøre noe mer med informasjonen vi mottar.
På fredag går vi mer gjennom dataobjekter (JSON / Dictionaries), som her kommer i form av en variabel: querystring
. Query betyr spørring (etter informasjon), som er verdien vi må endre for å påvirke resultatene.
I eksempelet har vi to verdier, country
og day
. Ulike APIer krever ulik info. Hvis vi tenker oss at vi vil hente informasjon fra ulike land, er det verdien til country
vi må endre:
Problemet nå er at vi oppdaterer querystring, der kun den siste definisjonen gjelder (island). Men, country
er bare tekst, som betyr at vi kan erstatte det med en variabel, som kan defineres gjennom funksjonen.
Vi kan derfor gjøre om på funksjonen vår ved å endre parametre inn til funksjonen, som er strukturert med: def <funksjon_navn>(<kommaseparerte parametre>):
- Funksjonen tar nå inn en parameter;
land
. - Her erstatter vi
"usa"
med vårt nye parameter;land
.
Hurra 🥳 - nå har vi en funksjon som henter data, basert på et eksternt parameter (land)!
Bonus: velg ut informasjon fra responsen
I eksempelet over skrives hele resultatet fra APIen ut som tekst, som ikke nødvendigvis er det vi ønsker, kanskje vi vil ha en app som viser antall innbyggere i ulike land? Da behøver vi kun den biten av informasjonen fra tjenesten.
Vi skal utforske JSON verdier, eller Python Dictionaries som de også heter i mer detalj på fredag.
Her er et eksempel på hvordan du kan hente ut population
verdien til resultatet:
I Example Responses
delen av RapidAPI, kan man se hvordan response body
-en ser ut, som er objektet vi får (response
variabelen). Her kan vi se alle nøklene som inneholder ulik informasjon, og kan notere oss hvilke som er relevante. Her kan vi se at under response
nøkkelen, finner man 0
, hvor vi finner nøkkelen population
:
For å velge ut denne, må vi konvertere response variabelen til en JSON
verdi. Vi navigerer gjennom JSON ved å bruke firkant-braketter ([ ]
), med tekst/nummer for å få verdien til den bestemte nøkkelen. Merk at en nøkkel, kan inneholde flere nøkler, som betyr gjentagelse av [ ]
symbolene:
Fredags kode
På fredag gikk vi gjennom mye rart! Mange dataobjekter (Lister og Dictionaries/JSON), løkker og match/case. Merk at det kan nok føles som mye, men man må nesten hoppe i det! Ikke vær redd for å google, vi kommer til å gjøre mange feil - og det er faktisk en positiv ting.
Funksjoner - Dad joke funksjoner
Video om å lage funksjoner fra ArjanCodes:
Vi laget noen funksjoner i en util.py
fil (Utilities), som vi importerer til en annen fil (bot.py
). En funksjon er noe som gjør noe, og kan returnere en verdi basert på det vi ønsker. Vi programmerte en funksjon som gir oss en tilfeldig dad-joke, og en funksjon som lar oss legge til flere dad-jokes.
random
modulen er en pakke som lar oss generere tilfeldigheter, f.eks. tilfeldig tall, eller objekt i liste-> str
forteller utvikleren / PyCharm om hva funksjonen generer, som er tekst (return <tekst>
)- Dette er en docstring, som er en forklaring på hva funksjonen gjør til mennesker som leser den
- Hypotetisk funksjon, vi kunne ha lastet inn dadjokes fra et API, eller fra en tekstfil
joke: str
betyr at verdien som blir sendt inn i funksjonen (joke) må være en streng/tekst- Hypotetisk funksjon, vi kunne ha lagret nye vitser til f.eks. en tekstfil.
Ekstra return
eksempel
Koden i util.py
gjør ingenting når man kjører den, men man kan importere funksjonene der vi skal ha vår chatbot, i en fil som heter bot.py
i samme mappe.
- Importer alle funksjoner fra
util.py
, slik at vi kan bruke dem while True:
er en løkke som vil gjenta seg for alltid (til programmet avsluttes), eller til koden treffer på enbreak
funksjonmatch
funksjonen lar deg enkelt sammenligne en verdi med ulikt utfall. Den fungerer på nesten samme måte somif input() == '?help'
, men har mange fordeler.case
er koden som vil kjøre dersom teksten matcher input fra bruker- Her bruker vi funksjonen fra
util.py
,get_dadjoke()
!
Lister
Lister er en av de store datatypene i Python som defineres av firkanta braketter ([]
) og inneholder flere verdier i en og samme variabel. Se Tuples og lister. I eksempelet over, har vi laget en liste over dadjokes. Objekter i en liste er separert med komma.
Dictionaries / Ordlister
Dictionaries er det viktigste og største dataformatet vi har, og kalles også ofte for JSON. (Se også Dataformater). Det er i dette formatet vi blant annet jobber med APIer eller eksterne ressurser. Ordlister defineres med curly brackets ({}
).
I motsetning til vanlige lister som over, definerer man verdier med nøkler / navn. Eksempler på nøkler kan være brukernavn, passord, e-post og lignende, i en liste over brukere. Merk at verdiene til nøkler kan være nye ordlister eller lister, som kan by på mange muligheter!
Ved hjelp av for
løkker kan man også gå gjennom alle enheter i en liste/ordliste, og utføre handlinger på flere datasett på samme tid. Nedenfor finner du et eksempel som gjør litt av hvert.
- Ordlister / dictionaries defineres av curly-brackets
{}
, der nøkkel/verdi settene skilles ved komma. - Du kan også lage lister som inneholder ordlister! Nyttig dersom man har en liste over for eksempel brukere
- Komma separer enhetene! Det er viktig!
For løkker
For løkker er UTROLIG viktige og nyttige, de lar oss iterere (gå gjennom en og en) verdier i lister, eller ordlister. Merk at navnet som settes mellom for/in (for <X> in
) , er valgfritt.
While løkker
While løkker er gjentagende kode som stopper når tilstanden ikke lenger er sann. Ofte bruker man en while løkke som sjekker om True
er sant, som det alltid vil være. Formålet med det er å definere kode som aldri stopper å kjøre. Dette gjelder alle applikasjoner som ikke stopper uten brukeren trykker stopp, som for eksempel i spill.
Bryt ut av en while løkke med break
, eller når en tilstand er møtt:
Dagens kode
Vi lagde 2 dokumenter, bot.py
og util.py
. Begge må ligge i samme mappe, slik at filene finner hverandre.
bot.py
Her ligger det litt ekstra som ikke er gått gjennom over, men som vi gikk gjennom litt ekstra i timen. Det gjelder:
- Bruk av
subprocess
- et eksempel på at det går an å gjøre ting på maskinen, som å åpne en kalkulator app via en chatbot - Legge til ekstra nøkler/verdier i en ordliste (hysj = vær stille)
- Legge til flere alternative skrivemåter i en
match/case
del via|
tegnet. - En funksjon (
roast_me(navn, alder)
) som sender informasjon fra bot.py til en util.py funksjon
util.py
Inkluderer en ekstra funksjon, roast_me(navn, alder)
som har en punchline over tid ved å bruke time
modulen.
Gjøremål
Motivasjon
Frem til jul skal dere definere et Python prosjekt, det kan være å opprette funksjoner på chatteroboten din, til å for eksempel hente data gjennom et API, eller legge til andre spenstige ting, som å kunne spille stein/saks/papir med en robot!
Du trenger ikke å forholde deg til chatteroboten din om du har andre ideer. Om du ønsker å teste andre språk - så må du gjerne det! Du finner oppgavetekst med litt inspirasjon på Teams.
Husk å last opp endringene dine til GitHub underveis, og eventuelt legg til informasjon om planene dine i README.md!