1 of 76

Palvelukehityksen perusteet

CODE02, Mayk

Lyhytlinkki: http://dy.fi/qbm

2 of 76

Palvelukehitys

Palvelu: aina käynnissä oleva, nettiä kuunteleva, pyyntöihin vastaava ohjelma

Palvelukehitys: miten saadaan aikaan netissä olevia palveluita

Palvelukehityksessä on monta puolta, seuraavassa ihan muutama

3 of 76

4 of 76

Ensimmäisellä tunnilla keskitytään siihen, että saadaan palvelu omalle koneelle

5 of 76

Toisella tunnilla keskitytään siihen, miten koodia julkaistaan ja muokataan yhdessä

6 of 76

Kolmannen tunnin aihe on palvelun saaminen nettiin

7 of 76

Palvelukehitys 1:�palvelu pyörimään koneella

(Windows-versio)

tämä on tärkeää palvelun kokeilemisen vuoksi

8 of 76

Asennukset

Tarvitaan: ennakoitavasti toimiva komentotila. Sellainen tulee Gitin mukana.

  • https://git-scm.com/downloads/win
  • "Select components": ei tarvitse muuttaa mitään
  • "Use Notepad++ as Git's default editor"
  • "Let Git decide"
  • "Git from the command line and also from 3rd-party software"
  • "Use bundled OpenSSH"
  • "Use the native Windows Secure Channel library"
  • "Checkout Windows-style, commit Unix-style line endings"
  • "Use MinTTY"
  • "Fast-forward or merge"
  • "Git Credential Manager"

9 of 76

Asetukset

Tarvitaan: python, jonka voi käynnistää komentotilasta

  • avaa Git Bash -niminen ohjelma, siinä voi kirjoittaa komentoja

$ cd OneDrive/

$ mkdir CODE02

$ cd CODE02/

$ export PATH="/c/ProgramData/anaconda3/:$PATH"

$ python --version

Python 3.11.7

Panu.Kalliokoski@MAYKS1312 MINGW64 ~/OneDrive/CODE02

$

10 of 76

Ensimmäinen versio

Tämä on webbisovellus, joka vastaa aina samalla tavalla. Tämän voi kirjoittaa esim. spyderissa. palvelu.py:

from wsgiref.simple_server import make_server

def app(environ, respond):

respond('200 OK', [('Content-type', 'text/plain; charset=utf-8')])

yield "Hello w€rld😞!".encode('utf-8')

if __name__ == '__main__':

with make_server("localhost", 8000, app) as server:

server.serve_forever()

11 of 76

Sovelluksen ajaminen omalla koneella

Tämä käynnistää verkkoyhteyksiä kuuntelevan sovelluspalvelinprosessin.

seuraava rivi tulee vasta, kun palvelua kokeillaan selaimella (seuraava slide)

Prosessin voi myös sammuttaa Ctrl-C:llä (ainakin jos on järkevä komentotulkki)

$ python kokeilu.py

127.0.0.1 - - [28/Feb/2025 11:09:32] "GET / HTTP/1.1" 200 11

12 of 76

Palvelun kokeileminen

Mene selaimella osoitteeseen localhost:8000

  • localhost on oman koneesi nettiosoite, kun olet omalla koneellasi
  • 8000 on ohjelmamme valitsema porttinumero, jossa palvelu kuuntelee

13 of 76

Mitä selaimen ja palvelun välillä kulkee?

Web developer tools löytyy valikoista tai Ctrl-Shift-E.

Tee reload (Ctrl-R tai F5).

Itse vastaus löytyy "Response"-kohdasta

Tässä on varsinainen kysely

Tässä vastauksen perustiedot

Tässä vastauksen lisätiedot

Tässä kyselyn lisätiedot

14 of 76

Iteraatio 1: Selaimen lähettämien tietojen käyttö

Nämä ovat app-funktiolle annetussa environ-parametrissa. Muuta app-funktio:

Tulostamme tiedot takaisin selaimelle, jotta näkyisi, mitä tietoja selain lähettää.

def app(environ, respond):

respond('200 OK', [('Content-type', 'text/plain; charset=utf-8')])

yield "Hello €nviron😞!\n\n".encode('utf-8')

for key in environ:

yield ("%s: %s\n" % (key, environ[key])).encode('utf-8')

15 of 76

Kokeilu

python (komentotilassa) pitää mahdollisesti käynnistää uudelleen.

Sitten reload.

Täällä on paljon hyödyllisiä tietoja! Erityisesti PATH_INFO ja QUERY_STRING näyttävät käyttökelpoisilta.

Myös wsgi.input mutta se ei oo merkkijono…

16 of 76

Iteraatio 2: salanimet

Muuta app-funktion koodi seuraavaan muotoon:

Tämän jälkeen pitää (totuttuun tapaan) uudelleenkäynnistää python ja ladata selaimessa sivu uudestaan

def app(environ, respond):

respond('200 OK', [('Content-type', 'text/plain; charset=utf-8')])

nimi = environ['PATH_INFO'].strip('/')

salanimi = nimi.replace('a', 'apa').replace('i', 'ipi') \

.replace('n', 'non').replace('na', 'nana')

yield ("salainen nimesi on: %s\n" % salanimi).encode('utf-8')

17 of 76

Kokeilu

Jipii, olemme onnistuneet tekemään dynaamisen (ja äärimmäisen hyödyllisen) palvelun! Sieltä saa salanimiä.

18 of 76

Iteraatio 3: ulkonäön viilausta

Se, miten selain näyttää sille lähetetyn datan, riippuu sisältötyypistä. Vaihdetaan se text/plain:sta text/html:ksi ja laitetaan muotoiluja sekaan.

def app(environ, respond):

respond('200 OK', [('Content-type', 'text/html; charset=utf-8')])

nimi = environ['PATH_INFO'].strip('/')

salanimi = nimi.replace('a', 'apa').replace('i', 'ipi') \

.replace('n', '<b>non</b>').replace('na', 'nana')

yield "<h1>huomio!</h1>".encode('utf-8')

yield ("<p>salainen <em>nimesi</em> on: %s</p>" % salanimi).encode('utf-8')

19 of 76

Oi miten paljon kauniimpaa

20 of 76

Palvelukehitys 1:�palvelu pyörimään koneella

(Linux-versio)

tämä on tärkeää palvelun kokeilemisen vuoksi

21 of 76

Asennukset

Tarvitaan: paikka, johon asentaa ohjelmistopaketteja

atehwa@kladakong:~/proj/code02$ mkdir tunti1

atehwa@kladakong:~/proj/code02$ cd tunti1/

atehwa@kladakong:~/proj/code02/tunti1$ python3 -m venv myenv

atehwa@kladakong:~/proj/code02/tunti1$ source myenv/bin/activate

(myenv) atehwa@kladakong:~/proj/code02/tunti1$

22 of 76

Asennukset

Tarvitaan: sovelluspalvelinohjelma

(myenv) atehwa@kladakong:~/proj/code02/tunti1$ pip install gunicorn

Collecting gunicorn

Downloading gunicorn-23.0.0-py3-none-any.whl (85 kB)

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 85.0/85.0 KB 4.4 MB/s eta 0:00:00

Collecting packaging

Using cached packaging-24.2-py3-none-any.whl (65 kB)

Installing collected packages: packaging, gunicorn

Successfully installed gunicorn-23.0.0 packaging-24.2

(myenv) atehwa@kladakong:~/proj/code02/tunti1$ gunicorn --version

gunicorn (version 23.0.0)

23 of 76

Ensimmäinen versio

Tämä on webbisovellus, joka vastaa aina samalla tavalla.

(myenv) atehwa@kladakong:~/proj/code02/tunti1$ cat palvelu.py

def app(environ, respond):

respond('200 OK', [('Content-type', 'text/plain; charset=utf-8')])

yield "Hello w€rld😞!".encode('utf-8')

24 of 76

Sovelluksen ajaminen omalla koneella

Tämä käynnistää verkkoyhteyksiä kuuntelevan sovelluspalvelinprosessin.

gunicornin voi myös sammuttaa Ctrl-C:llä (ainakin jos on järkevä komentotulkki)

(myenv) atehwa@kladakong:~/proj/code02/tunti1$ gunicorn palvelu:app

[2025-02-25 15:20:16 +0200] [4079377] [INFO] Starting gunicorn 23.0.0

[2025-02-25 15:20:16 +0200] [4079377] [INFO] Listening at: http://127.0.0.1:8000 (4079377)

[2025-02-25 15:20:16 +0200] [4079377] [INFO] Using worker: sync

[2025-02-25 15:20:16 +0200] [4079378] [INFO] Booting worker with pid: 4079378

25 of 76

Palvelun kokeileminen

Mene selaimella osoitteeseen localhost:8000

  • localhost on oman koneesi nettiosoite, kun olet omalla koneellasi
  • 8000 on gunicornin valitsema porttinumero, jossa palvelu kuuntelee

26 of 76

Mitä selaimen ja palvelun välillä kulkee?

Web developer tools löytyy valikoista tai Ctrl-Shift-E.

Tee reload (Ctrl-R tai F5).

Itse vastaus löytyy "Response"-kohdasta

Tässä on varsinainen kysely

Tässä vastauksen perustiedot

Tässä vastauksen lisätiedot

Tässä kyselyn lisätiedot

27 of 76

Iteraatio 1: Selaimen lähettämien tietojen käyttö

Nämä ovat app-funktiolle annetussa environ-parametrissa.

Tulostamme ne takaisin selaimelle, jotta näkyisi, mitä tietoja selain lähettää.

(myenv) atehwa@kladakong:~/proj/code02/tunti1$ cat palvelu.py

def app(environ, respond):

respond('200 OK', [('Content-type', 'text/plain; charset=utf-8')])

yield "Hello €nviron😞!\n\n".encode('utf-8')

for key in environ:

yield ("%s: %s\n" % (key, environ[key])).encode('utf-8')

28 of 76

Kokeilu

gunicorn pitää mahdollisesti käynnistää uudelleen.

Sitten reload.

Täällä on paljon hyödyllisiä tietoja! Erityisesti PATH_INFO ja QUERY_STRING näyttävät käyttökelpoisilta.

Myös wsgi.input mutta se ei oo merkkijono…

29 of 76

Iteraatio 2: salanimet

Muuta palvelumme koodi seuraavaan muotoon:

Tämän jälkeen pitää (totuttuun tapaan) uudelleenkäynnistää gunicorn ja ladata selaimessa sivu uudestaan

(myenv) atehwa@kladakong:~/proj/code02/tunti1$ cat palvelu.py

def app(environ, respond):

respond('200 OK', [('Content-type', 'text/plain; charset=utf-8')])

nimi = environ['PATH_INFO'].strip('/')

salanimi = nimi.replace('a', 'apa').replace('i', 'ipi') \

.replace('n', 'non').replace('na', 'nana')

yield ("salainen nimesi on: %s\n" % salanimi).encode('utf-8')

30 of 76

Kokeilu

Jipii, olemme onnistuneet tekemään dynaamisen (ja äärimmäisen hyödyllisen) palvelun! Sieltä saa salanimiä.

31 of 76

Iteraatio 3: ulkonäön viilausta

Se, miten selain näyttää sille lähetetyn datan, riippuu sisältötyypistä. Vaihdetaan se text/plain:sta text/html:ksi ja laitetaan muotoiluja sekaan.

(myenv) atehwa@kladakong:~/proj/code02/tunti1$ cat palvelu.py

def app(environ, respond):

respond('200 OK', [('Content-type', 'text/html; charset=utf-8')])

nimi = environ['PATH_INFO'].strip('/')

salanimi = nimi.replace('a', 'apa').replace('i', 'ipi') \

.replace('n', '<b>non</b>').replace('na', 'nana')

yield "<h1>huomio!</h1>".encode('utf-8')

yield ("<p>salainen <em>nimesi</em> on: %s</p>" % salanimi).encode('utf-8')

32 of 76

Oi miten paljon kauniimpaa

33 of 76

Flask

environ:n PATH_INFOn ja varsinkin QUERY_STRINGin jäsentäminen on vaivalloista. "Web framework" (verkkosovelluskehys?) on kirjasto, joka helpottaa gunicornin (tai oikeastaan WSGI-rajapinnan) käyttöä. Otamme minimalistisen sovelluskehyksen, joka on nimeltään Flask.

(myenv) atehwa@kladakong:~/proj/code02/tunti1$ pip install flask

Collecting flask

[...]

34 of 76

Flask-sovelluksen rakenne

… näyttää aika erilaiselta kuin puhdas WSGI.

Ajaminen käy sen sijaan hyvinkin samalla tavalla:

from flask import Flask

app = Flask(__name__)

@app.route("/")

def hello_world():

return "<p>Hello, World!</p>"

$ gunicorn muntiedosto:app

35 of 76

Jos vielä jää aikaa…

… niin jatketaan Flask-tutoriaalilla

https://flask.palletsprojects.com/en/stable/quickstart/

36 of 76

Palvelukehitys 2: koodin hallinta ja yhteistyöstö

Tätä tarvitaan myös, jotta voi julkaista palveluita

37 of 76

Muistutuksena iso kuva: miten koodia julkaistaan ja muokataan yhdessä

38 of 76

Versiohallinnan pointti

https://bitbucket.org/product/version-control-software

https://git-scm.com/book/ms/v2/Getting-Started-About-Version-Control

https://www.geeksforgeeks.org/version-control-systems/

Versiohallinta ei itse asiassa liity mitenkään erityisesti koodiin.

… paitsi, että se toimii huonosti muulle kuin raakatekstille.

39 of 76

Ihan alkuun pääsy

https://git-scm.com/book/en/v2/Git-Basics-Getting-a-Git-Repository

(myenv) atehwa@kladakong:~/proj/code02/tunti1$ git init

hint: [...]

Initialized empty Git repository in /home/atehwa/proj/code02/tunti1/.git/

(myenv) atehwa@kladakong:~/proj/code02/tunti1$ git checkout -b main

Switched to a new branch 'main'

(myenv) atehwa@kladakong:~/proj/code02/tunti1$ git config user.email atehwa@sange.fi

40 of 76

sisällön lisääminen gitiin

https://git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository

(myenv) atehwa@kladakong:~/proj/code02/tunti1$ git add palvelu.py

(myenv) atehwa@kladakong:~/proj/code02/tunti1$ git commit -m "salanimipalvelu"

[main (root-commit) ae0aa0d] salanimipalvelu

1 file changed, 9 insertions(+)

create mode 100644 palvelu.py

41 of 76

Mitä muutoksia on tehty?

Git log kertoo commitilla talteen viedyt muutokset, git diff ne joita ei ole vielä viety

(myenv) atehwa@kladakong:~/proj/code02/tunti1$ git log

commit 1d1fb92877a95bdce5cfbc96a9736b8554487730 (HEAD -> main)

Author: Panu Kalliokoski <atehwa@sange.fi>

Date: Tue Feb 25 17:13:44 2025 +0200

dependencies

commit ae0aa0d716fff4e3cc773b0a0f46e2b0837873d0

Author: Panu Kalliokoski <atehwa@sange.fi>

Date: Tue Feb 25 17:11:48 2025 +0200

salanimipalvelu

42 of 76

Mitä muutoksia on tehty?

Jos muokkaan tiedostoa, git diff huomaa sen

(myenv) atehwa@kladakong:~/proj/code02/tunti1$ git diff

diff --git a/palvelu.py b/palvelu.py

index 7244ee1..1472026 100644

--- a/palvelu.py

+++ b/palvelu.py

@@ -2,8 +2,6 @@

def app(environ, respond):

respond('200 OK', [('Content-type', 'text/html; charset=utf-8')])

nimi = environ['PATH_INFO'].strip('/')

- salanimi = nimi.replace('a', 'apa').replace('i', 'ipi') \

- .replace('n', '<b>non</b>').replace('na', 'nana')

yield "<h1>huomio!</h1>".encode('utf-8')

- yield ("<p>salainen <em>nimesi</em> on: %s</p>" % salanimi).encode('utf-8')

+ yield ("<p><em>nimesi</em> on: %s</p>" % nimi).encode('utf-8')

43 of 76

Voin tallettaa osan tai kaikki muutokset

git add -p + git commit vie talteen haluamasi muutokset.�git commit -a vie kaikki.

(Tämän jälkeen usein viedään muutokset Githubiin komennolla git push.)

git log -p -komennolla voit tarkastella, mitä on tapahtunut missäkin muutoksessa.

https://git-scm.com/book/en/v2/Git-Basics-Viewing-the-Commit-History

44 of 76

Github-tunnuksen perustaminen

https://github.com/signup

45 of 76

Tee itsellesi säilö (repository)

Tämä on koodisi �julkaisua varten.

tähän tarvitsee säätöä (seuraava slide)

46 of 76

Githubiin joutuu nykyään tekemään kaikenlaista säätöä

Muutokset, joita�git remote add�-komentoon pitää tehdä

tähän tuli yksi vaihe lisää, klikkaa "personal access tokens"

$ git remote add origin https://atehwajotain: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@github.com/atehwajotain/code02-tunti1.git

$ git push -u origin main

47 of 76

Vihdoin, git-muutosten vienti luotuun repositoryyn

Alla oleva git remote add -komento pitää muodostaa githubin ohjeista, käyttäjätunnuksestasi ja äsken luodusta salasanasta.

atehwa@kladakong:~/proj/code02/tunti1$ ls

myenv palvelu.py __pycache__ requirements.txt

atehwa@kladakong:~/proj/code02/tunti1$ git remote add origin https://jokutosihieno435:ghp_grt7Ws7FNSGl1oILlF90Ad82A@github.com/jokutosihieno435/web-palvelu.git

atehwa@kladakong:~/proj/code02/tunti1$ git push -u origin main

Enumerating objects: 12, done.

Counting objects: 100% (12/12), done.

[...]

48 of 76

Perustyöskentelytapa gitin kanssa

git pull --ff-only — bring your local working directory up-to-date

  1. edit files etc. in an ordinary way
    • git add file.txt — tell git about a new file to be tracked
  2. make a commit out of a logical set of changes
    • git commit -am description — commit all new work
    • git add -p; git commit -m description — commit only some part
  3. repeat from (2) if you don't want to publish your changes yet
  4. git pull --rebase — merge your work with what others have been doing
  5. git push — publish your work to your remote repository
  6. go home.

49 of 76

Extra: älä tee tätä automaattisesti! Harjoitus 1

  • create a Github account
  • create a repository
  • clone your repository
  • test basic git workflow

50 of 76

Extra: älä tee tätä automaattisesti! Harjoitus 2

  • git clone https://(tunnus)@github.com/atehwajotain/git-harjoitus.git
  • cd git-harjoitus
  • oman tiedoston perustaminen, koko workflow
  • muiden tiedostojen muokkaaminen + konfliktit

51 of 76

Palvelukehitys 3: oma palvelu nettiin

Sitten sitä voi esitellä sukulaisille.

52 of 76

Muistutus, missä mennään isossa kuvassa

53 of 76

Taas lisää webbipalveluita!

https://dashboard.render.com/register

54 of 76

render.com tekee lähdekoodistamme virtuaalikoneen

Odota, että se sanoo:

sitten:

55 of 76

Palvelun päivittäminen

Muokataan palvelua (testaus!), viedään muutokset versiohallintaan ja julkaistaan:

atehwa@kladakong:~/proj/code02/tunti1$ git add -p

[...]

yield "<h1>huomio!</h1>".encode('utf-8')

+ yield "<hr size=5>".encode('utf-8')

yield ("<p><em>nimesi</em> on: %s</p>" % nimi).encode('utf-8')

(1/1) Stage this hunk [y,n,q,a,d,e,?]? y

atehwa@kladakong:~/proj/code02/tunti1$ git commit -m "väliviiva"

[main 38cae79] väliviiva

1 file changed, 1 insertion(+)

atehwa@kladakong:~/proj/code02/tunti1$ git push -u origin main

Enumerating objects: 5, done.

Counting objects: 100% (5/5), done.

[...]

56 of 76

muutos näkyy githubissa

57 of 76

render.com pitää erikseen kehottaa päivittämään palvelu

Samat odottelut taas

Nykyään näemmä render tekee tän myös automaattisesti kun tulee uusi commit sen seuraamaan haaraan (main)

58 of 76

Palvelukehitys 4: monimutkaisempi palvelu

Kehitetään jotain mikä reagoi

59 of 76

Olisko nyt oikeasti jonkin kunnon web-frameworkin aika :0

Aletaan tässä vaiheessa tehdä Flaskilla juttuja :)

Usein palvelun pitäisi tehdä ihan eri asioita riippuen siitä, mikä esimerkiksi on selaimeen kirjoitettu osoite (joka tulee environ['PATH_INFO']:ssa meille) ja monista muista asioista riippuen.

Web framework (esim Flask) auttaa app:n saamien syötteiden (argumenttien) jäsentämisessä ja vastauksen muodostamisessa selaimelle.

60 of 76

Valmis esimerkkisovellus

Tätä varten Githubissa on valmis sovellus, joka on tehty flaskilla.

Sovellus on täällä: https://github.com/jokutosihieno435/hieno-lomake

Tee siitä itsellesi fork, jotta voit helposti julkaista muunneltuja versioita siitä (eli paina "Fork" oikealla ylhäällä)

Sen jälkeen voit tehdä omasta forkistasi (Githubissa) itsellesi kloonin (omalla koneellasi). Ota "code"-kohdasta repon osoite, mutta siihen pitää taas editoida käyttäjätunnus ja salasana kuten aiemmin.

61 of 76

Esimerkkisovelluksen osat

https://github.com/jokutosihieno435/hieno-lomake/blob/main/main.py:

  • sisältää määrittelyn, mitä tekevät osoitteet "/" ja "/vastaus"
  • käyttää render_templatea joka hakee sivut templates-hakemistosta

https://github.com/jokutosihieno435/hieno-lomake/blob/main/templates/lomake.html:

  • sivu, joka näytetään, kun tullaan osoitteeseen "/"

https://github.com/jokutosihieno435/hieno-lomake/blob/main/templates/vastaus.html:

  • sivu, joka näytetään osoitteessa "/vastaus"

62 of 76

Esimerkkisovelluksen osat (jatkoa)

https://github.com/jokutosihieno435/hieno-lomake/blob/main/main.py#L11:

  • kun käyttäjä on kirjoittanut lomakkeeseen nimensä ja lähettänyt sen, tällä rivillä tuo nimi jonka selain on vienyt sivun osoitteeseen haetaan request.args -dictionarysta
  • render_template antaa sille annetut muuttujat (kuten tässä "nimi=") Jinjalle joka interpoloi ne template-tiedostoon siihen kohtaan jossa sanotaan {{nimi}}

https://github.com/jokutosihieno435/hieno-lomake/blob/main/static/tyylit.css:

  • templates/lomake.html viittaa tähän tiedostoon. Täällä olevat määrittelyt kertovat, miltä mikin osa sivusta näyttää.

63 of 76

Ehdotuksia jatkoprojekteiksi

  • muuta lomakkeen antamaa vastausta
  • tee nimelle erilaisia temppuja
  • lisää lomakkeeseen uusia kenttiä
  • kehitä sivujen ulkonäköä, esim. vastaus.html voisi olla oikeasti HTML:a
  • kehitä sivujen ulkonäköä muokkaamalla tyylit.css:a
  • tee uusia osoitteita, esim. /poks
  • tee sivuihin uusia siirtymiä, siis linkkejä (<a href=...>) tai lomakkeita sivulta toiselle

64 of 76

Esimerkki Panun jatkokehityksestä

Tein pysäkkiaikatauluja näyttävän palvelun, sen lähdekoodi on täällä:

https://github.com/pkalliok/hieno-lomake

Seuraavat slidet kertovat, miten Flask-sovellusta lähdetään tekemään tyhjästä.

65 of 76

Flask-sovelluksen kehitys alusta

66 of 76

Asennukset

Tarvitaan: paikka, johon asentaa ohjelmistopaketteja

atehwa@kladakong:~/proj/code02$ mkdir tunti1

atehwa@kladakong:~/proj/code02$ cd tunti1/

atehwa@kladakong:~/proj/code02/tunti1$ python3 -m venv myenv

atehwa@kladakong:~/proj/code02/tunti1$ source myenv/bin/activate

(myenv) atehwa@kladakong:~/proj/code02/tunti1$

67 of 76

Flask

environ:n PATH_INFOn ja varsinkin QUERY_STRINGin jäsentäminen on vaivalloista. "Web framework" (verkkosovelluskehys?) on kirjasto, joka helpottaa gunicornin (tai oikeastaan WSGI-rajapinnan) käyttöä. Otamme minimalistisen sovelluskehyksen, joka on nimeltään Flask.

(myenv) atehwa@kladakong:~/proj/code02/tunti1$ pip install flask

Collecting flask

[...]

68 of 76

Otetaan asennetut kirjastot muistiin

Saadaan samalla esimerkki tokasta muutoksesta

https://git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository

(myenv) atehwa@kladakong:~/proj/code02/tunti1$ pip freeze > requirements.txt

(myenv) atehwa@kladakong:~/proj/code02/tunti1$ git add requirements.txt

(myenv) atehwa@kladakong:~/proj/code02/tunti1$ git commit -m "dependencies"

[main 1d1fb92] dependencies

1 file changed, 9 insertions(+)

create mode 100644 requirements.txt

69 of 76

Flask-sovelluksen rakenne

… näyttää aika erilaiselta kuin puhdas WSGI.

Ajaminen käy Flaskin omalla komennolla, jos haluaa kaikenlaisia kätevyyksiä:

from flask import Flask

app = Flask(__name__)

@app.route("/")

def hello_world():

return "<p>Hello, World!</p>"

$ flask --app muntiedosto run -h localhost -p 8000

70 of 76

Teoreettiset ekstrat

käytettäväksi sopivassa välissä

71 of 76

Teoreettista lisäkamaa: www-sovelluksen tilakäsittely

www-sovellus toimii näin:

  1. selain saa osoitteen (eli tilan, johon pitää mennä)
  2. selain kysyy palvelimelta, miltä kyseinen tila näyttää
  3. palvelin kertoo sen selaimelle (yleensä HTML:na)
  4. tästä eteenpäin palvelin (eli meidän ohjelmamme) ei tiedä yhtään mitä selaimessa tapahtuu, ennen kuin käyttäjä aktivoi jotain (eli klikkaa linkkiä tai lähettää lomakkeen)
  5. selain muodostaa uuden osoitteen linkistä tai lomakkeen sisällöstä
  6. nyt selaimella on uusi osoite, joten se jatkaa taas kohdasta 1.

72 of 76

Teoreettista lisäkamaa: www-sovelluksen tilakäsittely

Esim. hieno-lomake-palvelussamme tämä toimii näin:

  1. selaimeen kirjoitetaan http://localhost:5000/
  2. selain ottaa yhteyttä palvelimeen localhost:5000 ja pyytää sivun "/"
  3. meidän ohjelmamme kertoo, miltä se näyttää (siellä on mm. <form>)
  4. selain antaa meidän täyttää lomaketta tai klikata linkkejä
  5. kun olemme täyttäneet lomakkeen, selain muodostaa uuden osoitteen http://localhost:5000/vastaus?nimi=Jipii
  6. Nyt koska selaimella on uusi osoite, se ottaa yhteyttä uudelleen palvelimeen localhost:5000 ja pyytää sivun "/vastaus?nimi=Jipii"

73 of 76

Teoreettista lisäkamaa: tekstiohjelma www-ohjelmaksi

Jokainen tilanne, jossa ohjelma näyttää joltain ja odottaa käyttäjän syötettä, on yksi ohjelman tila. Esimerkiksi tässä ohjelmassa on melko selvästi kolme tilaa.

74 of 76

Teoreettista lisäkamaa: tekstiohjelma www-ohjelmaksi

Jokaisesta alkuperäisen ohjelman tilasta pitää tehdä www-ohjelman tila. Ja koska www:ssä tila tarkoittaa tiettyä osoitetta, jokaisella tilalla pitää olla oma osoite.

75 of 76

Teoreettista lisäkamaa: tekstiohjelma www-ohjelmaksi

Jokaiseen sivuun pitää antaa ohjeet selaimelle, mihin tiloihin siitä pääsee. Esimerkiksi tässä /menu -tilan sisältämät linkit ovat selaimelle siirtymäohjeita, mihin tiloihin menusta voi siirtyä.

76 of 76

Panu Kalliokoski, 2025. Käytetty Helsingin matematiikkalukion CODE02-kurssilla.

Kysymyksiä voi lähettää:

panu.kalliokoski@sange.fi