PythonAnywhere

PythonAnywhere on selaimessa toimiva Python-ympäristö, johon saa julkaistua web-sovelluksen ilman omaa palvelinta tai asennuksia. Kurssilla sitä käytetään viikkotehtävissä 1 ja 3.

Kolme ympäristöä, yksi sovellus

Kurssin aikana samanlaisia Flask-sovelluksia ajetaan kolmella eri tavalla: PythonAnywheressä WSGI-rajapinnan kautta, users.jyu.fi-palvelimella CGI-ohjelmana ja lopuksi Cloud Runissa konttina. Sovelluskoodi on kaikissa sama; vain käynnistystapa ja ympäristön rajoitukset vaihtuvat. Siksi kannattaa opetella, mikä kussakin on erilaista.

Tili

Rekisteröityessä valittu käyttäjänimi näkyy sovelluksen osoitteessa muodossa https://kayttajanimi.pythonanywhere.com/, eikä sitä voi jälkikäteen vaihtaa. Valitse siis nimi, jonka kehtaa laittaa palautukseen.

Ilmaistili riittää kurssin tehtäviin, mutta sen ehdot ovat kiristyneet vuoden 2026 alusta. Olennaisimmat:

Muutokset on kuvattu palvelun blogikirjoituksessa Changes on PythonAnywhere Free Accounts. Ehdot muuttuvat aika ajoin, joten tarkista voimassa olevat rajat palvelun omilta sivuilta.

Käyttöliittymä

Välilehdet ja niiden tehtävät
VälilehtiMitä siellä tehdään
Consoles Bash-pääte ja Python-tulkki selaimessa. Täällä luodaan virtuaaliympäristö, asennetaan paketteja ja haetaan koodi versionhallinnasta.
Files Tiedostojen selaaminen, lataaminen ja selaimessa toimiva editori.
Web Web-sovelluksen asetukset: WSGI-konfiguraatiotiedosto, virtuaaliympäristön polku, staattiset tiedostot, lokit ja Reload-painike.
Databases MySQL- ja Postgres-kannat. Ilmaistilillä ei käytettävissä.
Tasks Ajastetut tehtävät. Ilmaistilillä ei käytettävissä.

Web-sovelluksen luominen

Web-välilehdellä valitaan Add a new web app. Kysymyksiä tulee kolme:

  1. Osoite. Ilmaistilillä se on kayttajanimi.pythonanywhere.com, eikä vaihtoehtoja ole.
  2. Sovelluskehys. Valitse Manual configuration, jos haluat kirjoittaa WSGI-konfiguraatiotiedoston itse, tai Flask, jolloin palvelu luo valmiin runkosovelluksen. Kurssin kannalta manuaalinen on opettavaisempi, koska silloin näkee, mikä sovelluksen oikeasti käynnistää.
  3. Python-versio. Tätä ei voi vaihtaa jälkikäteen — version vaihtaminen tarkoittaa sovelluksen poistamista ja uuden luomista. Valitse sama versio, jota käytät omalla koneellasi.

Sovellus syntyy kotihakemistoosi, oletuksena kansioon mysite. Valmis sovellus vastaa heti osoitteessaan; HTTPS-varmenne tulee automaattisesti pythonanywhere.com-alidomainille.

WSGI-konfiguraatiotiedosto

Tämä on se kohta, joka hämmentää eniten. PythonAnywhere ei suorita sovellustiedostoasi suoraan, vaan lukee Web-välilehdellä mainitun WSGI configuration file -tiedoston ja etsii siitä application-nimistä oliota. Flask-sovelluksessa se on oma app-olio uudelleen nimettynä:

import sys

#Oman koodin kansio on lisättävä hakupolkuun, muuten importti ei löydä sitä.
polku = "/home/oma_tunnus/mysite"
if polku not in sys.path:
    sys.path.insert(0, polku)

#oma.py sisältää rivin app = Flask(__name__)
from oma import app as application

Sisällöltään tämä vastaa users.jyu.fi-palvelimen flask.cgi-tiedostoa: molemmat ovat käärekoodia, joka kertoo palvelimelle, mistä sovellus löytyy.

Virtuaaliympäristö

Palvelussa on valmiina joukko yleisiä kirjastoja, myös Flask. Virtuaaliympäristöä tarvitaan, kun haluat tietyn version kirjastosta tai paketin, jota ei ole valmiina. Se luodaan Consoles-välilehden bash-päätteessä:

mkvirtualenv --python=/usr/bin/python3.12 oma-ymparisto
pip install Flask Flask-WTF

Tämän jälkeen ympäristön polku on kirjoitettava Web-välilehden Virtualenv-kenttään, esimerkiksi /home/oma_tunnus/.virtualenvs/oma-ymparisto. Pelkkä asentaminen ei riitä: ilman kenttään kirjoitettua polkua sovellus käyttää yhä järjestelmän omaa Pythonia eikä löydä asentamiasi paketteja. Tämä on yksi yleisimmistä ImportError-virheen syistä.

Reload

Koodimuutokset eivät näy ilman uudelleenkäynnistystä

WSGI-sovelluksessa Python-tulkki jää muistiin pyyntöjen välillä. Muokattu koodi tulee käyttöön vasta, kun sovellus käynnistetään uudelleen Web-välilehden Reload-painikkeella. Sama koskee virtuaaliympäristön ja asetusten muutoksia.

Tämä on ylivoimaisesti yleisin hämmennyksen aihe: koodi on muutettu ja tallennettu, mutta selain näyttää yhä vanhaa. Huomaa ero users.jyu.fi-palvelimeen, jossa CGI käynnistää tulkin joka pyynnöllä uudelleen eikä uudelleenkäynnistystä tarvita.

Lokit ja virheiden etsiminen

Kun sovellus ei toimi, selaimeen tulee lakoninen Something went wrong -sivu. Varsinainen virheilmoitus on lokitiedostoissa, jotka löytyvät Web-välilehden Log files -kohdasta.

LokiSisältö
error.log Virheilmoitukset ja pinolistaukset eli kaikki standardivirheeseen kirjoitettu. Katso tänne ensin.
server.log Sovelluksen käynnistykset ja standarditulostus, eli myös print-kutsujen tulosteet.
access.log Kuka on ladannut minkäkin resurssin ja milloin.
import sys

print("tämä näkyy server.logissa")
print("tämä näkyy error.logissa", file=sys.stderr)

Virheet saa myös suoraan selaimeen lisäämällä WSGI-konfiguraatiotiedoston loppuun:

from werkzeug.debug import DebuggedApplication

application.debug = True
application = DebuggedApplication(application)

Muista, että pinolistaukset paljastavat lähdekoodia kaikille sivun avaajille, joten tämä on vain kehitysapu.

print toimii täällä, muttei kaikkialla

PythonAnywheressä print menee lokiin ja on siksi kelvollinen pikainen debuggauskeino. users.jyu.fi-palvelimella sama rivi menisi CGI-ohjelmassa suoraan selaimelle ja rikkoisi vastauksen. Jos haluat kirjoittaa koodia, joka toimii molemmissa, käytä app.logger-lokitusta.

Staattiset tiedostot

Tyylitiedostot, kuvat ja skriptit kannattaa tarjoilla palvelimelta suoraan eikä Flaskin läpi. Web-välilehden Static files -taulukkoon lisätään rivi, jossa vasemmalla on osoite ja oikealla hakemistopolku:

/static/    /home/oma_tunnus/mysite/static/

Templateissa osoitteet muodostetaan tästä huolimatta tavalliseen tapaan url_for-funktiolla:

<link rel="stylesheet" href="{{ url_for('static', filename='tyyli.css') }}" />

Koodin siirtäminen palvelimelle

Vaihtoehtoja on kolme: selaimen editori Files-välilehdellä, tiedoston lataaminen ja versionhallinta. Käytä versionhallintaa. Kurssilla koodi on joka tapauksessa GitLabissa, ja silloin muutokset siirtyvät yhdellä komennolla eivätkä versiot pääse eroamaan toisistaan:

git clone https://gitlab.jyu.fi/oma_tunnus/vt1.git
cd vt1
git pull          #jatkossa muutokset haetaan näin

Muista git pull -komennon jälkeen Reload.

Tietokanta

Uusilla ilmaistileillä MySQL ei ole käytettävissä. Se ei haittaa, koska kurssin tehtävissä käytetään SQLiteä, joka on yhdessä tiedostossa eikä vaadi tietokantapalvelinta.

Sijoita kantatiedosto kansioon, jota ei tarjoilla staattisena hakemistona — muuten kuka tahansa voi ladata koko kannan selaimellaan. Sama koskee sessiotiedostoja ja lokeja.

Salaiset avaimet ja asetukset

Salaista avainta tai tunnuksia ei kirjoiteta lähdekoodiin eikä versionhallintaan. PythonAnywheressä ne on helpointa asettaa ympäristömuuttujiksi WSGI-konfiguraatiotiedostossa, joka ei ole osa versionhallittua projektia:

import os

os.environ["SECRET_KEY"] = "tähän arvottu avain"

from oma import app as application

Sovellus lukee arvon tavalliseen tapaan:

app.secret_key = os.environ["SECRET_KEY"]

Avaimen voi arpoa komennolla python3 -c "import secrets; print(secrets.token_hex(32))". Huomaa, että ympäristömuuttujat on asetettava ennen sovelluksen tuontia.

Ilmaistilin rajoitukset

Erot users.jyu.fi-palvelimeen

PythonAnywhere (WSGI)users.jyu.fi (CGI)
Käynnistystiedosto WSGI-konfiguraatiotiedosto flask.cgi
Prosessimalli Tulkki jää muistiin Uusi tulkki joka pyynnölle
Koodimuutos käyttöön Reload-painikkeella Heti seuraavalla pyynnöllä
print-tuloste Menee lokiin Menee selaimelle ja rikkoo vastauksen
Lokit Luettavissa Web-välilehdeltä Ei pääsyä; kirjoitettava omaan tiedostoon
Tiedosto-oikeudet Ei tarvitse säätää Tarkat vaatimukset, ks. pääteohjaus 1
Ulkoiset yhteydet Vain sallitulta listalta Vapaasti

Kummassakaan ympäristössä sovelluksen tilaa ei voi säilyttää globaalissa muuttujassa: CGI:ssä tulkki nollautuu joka pyynnöllä, ja WSGI-sovelluskin käynnistetään uudelleen milloin tahansa.

Yleisimmät virheet

OireTodennäköinen syy
Muutokset eivät näy selaimessa Reload painamatta
ImportError lokissa Virtualenv-kenttä tyhjä, väärä polku sys.path-lisäyksessä tai väärä moduulin nimi
Something went wrong Sovellus kaatui käynnistyessä — katso error.log
Tyylitiedosto tai kuva 404 Static files -rivi puuttuu tai polun lopusta puuttuu kauttaviiva
Ulkoinen haku ei toimi Osoite ei ole sallittujen listalla
Sovellus lakkasi toimimasta itsestään Käyttämätön web-sovellus vanheni — uusi se Web-välilehdeltä
Sivu latautuu hitaasti Päivittäinen prosessoriaikakiintiö täynnä

Lisätietoa

Käyttäjien kommentit

Kommentoi Lisää kommentti