Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointiongelmat: Python ja virheet

Sivu 1 / 1

Sivun loppuun

kyyhky89 [04.09.2019 20:03:53]

Lainaa #

Hei kaikille. Olisin kysynyt seuraavaa. Olen rakentanut ohjelman, missä on tuhansia rivejä ja kymmenittäin aliohjelmia. Joskus jokin ohjelman osa aiheuttaa virheen, mikä ei kaada ohjelmaa. Ongelma on se, että en tiedä ohjelmaa ajaessani virheestä mitään, saattaa esim. jäädä jokin tallennus toteutumatta. Onko olemassa keinoa, että ohjelma varoittaa minua siinä tapauksessa, että ohjelman suorituksessa on tapahtunut virhe. Kiitos:-)

Grez [05.09.2019 07:41:12]

Lainaa #

Miten olet toteuttanut sen, että virhe "ei kaada ohjelmaa"? Muutat ne kohdat niin, että se varoittaa.

The Alchemist [07.09.2019 05:54:28]

Lainaa #

Olet siis toteuttanut virheidenkäsittelyn päin helvettiä, koska et oikeasti käsittele virheitä vaan pelkästään "kaappaat" ja piilotat ne.

Metabolix [07.09.2019 14:15:50]

Lainaa #

Pythonissa virheet tulevat pääosin poikkeuksina. Ilman käsittelyä poikkeus kaataa ohjelman (tai ainakin säikeen) ja virhetiedot tulostuvat konsoliin. Jos näin ei tapahdu, varmaankin sinulla on koodissasi poikkeusten käsittely eli try–except-rakenne. Jos et tiedä, missä virhe tapahtuu, tarkasta ohjelmastasi kaikki except-lohkot ja varmista, että jokaisessa niistä jollain tavalla ilmoitat virheestä.

Yleensä try–except-rakenne kannattaa sijoittaa sinne, missä virhe voi tapahtua ja siihen voidaan reagoida järkevästi.

kyyhky89 [09.09.2019 14:06:40]

Lainaa #

Hei. Luulin, että ongelma on yleinen, mutta ei sitten ilmeisesti ole? Vaikka ajan ohjelmaa lukemattomia kertoja, niin joskus harvoin virheitä tulee, joskus kaatuu, joskus ei. Joskus saan tällaisen virheilmoituksen "RuntimeError: maximum recursion depth exceeded". Joskus puolestaan taulukon tallennus epäonnistuu ja .xlsx taulukko rikkoutuu. Se ei pysäytä ohjelmaa, mutta tallennus loppuu siitä tietämättä. En edes tiedä missä kohtaa ohjelma on menossa virheiden tapahtuessa, koska en osaa ennakoida näitä.

Grez [09.09.2019 14:37:34]

Lainaa #

kyyhky89 kirjoitti:

Hei. Luulin, että ongelma on yleinen, mutta ei sitten ilmeisesti ole?

Jos yleisellä tasolla ohjelmointikielessä (esim. Pythonissa) olisi ongelma, että "ohjelman osa aiheuttaa virheen, mikä ei kaada ohjelmaa", niin eihän kukaan käyttäisi sellaista ohjelmointikieltä.

Nyt myöhemmin kertomasi perusteella tämän tyyppinen ongelma on ilmeisesti jossain xlsx:ää käsittelevässä kirjastossa. Et ole kertonut mitä kirjastoa käytät, mutta yleensä suosittujen kirjastojen kanssa esiintyviin ongelmiin löytyy hyvin tietoa netistä. Tähän mennessä kertomasi perusteella tuskin kukaan ohjelmointiputkan käyttäjä osaa siihen suoraan antaa vastausta, ellei sitten joku ole törmännyt tasan samaan ongelmaan itsekin. (Eli käyttänyt samaa xlsx-kirjastoa ja tehnyt sillä samantyyppisiä asioita)

kyyhky89 kirjoitti:

Vaikka ajan ohjelmaa lukemattomia kertoja, niin joskus harvoin virheitä tulee, joskus kaatuu, joskus ei.

Tämän tyyppisten ongelmien ratkaisu on useinkin osa ohjelmoijan perustyötä. Hyvällä suunnittelulla ja hyvillä välineillä ongelmia tulee harvemmin vastaan, mutta juuri tuollainen hyvin harvoin toistuva ongelma joka voi johtua vaikka bugista jossain ulkoisessa kirjastossa on ehkä hankalimmin korjattava. Itse ehkä vastaavassa tilanteessa tekisin ohjelmaan jonkin tarkistuksen että onko ohjelman ajamisen jälkeen taulukko vioittunut ja jos on niin lokittaisin kaikki syötetiedot myöhempää analysointia varten.

Yleensä kun bugia korjataan, pyritään ensin määrittelemään "steps to repdroduce" eli mitä pitää tehdä että virhe tulee esille.

Jos ohjelma täsmälleen samoilla syötteillä antaa silloin tällöin virheen ja silloin tällöin ei (eli toimii satunnaisesti) niin ohjelman rakenteessa on todennäköisesti jotain pahasti vialla.

kyyhky89 kirjoitti:

Joskus saan tällaisen virheilmoituksen "RuntimeError: maximum recursion depth exceeded".

Pythonissa on rekursiosyvyys on oletuksena max 999. Normaalisti jos ohjelma on kunnollisesti toteutettu, tuon pitäisi kyllä riittää. Syvyyttä voi kasvattaa, mutta ei rajattomasti, eikä se luultavasti ole oikea ratkaisu ongelmaasi.

Pythonissa ei ole rekursio-optimointia sisäänrakennettuna, kuten funktionaalisissa kielissä, joten jos toteutat jonkin asian toteutuksen rekursiona, niin kannattaa optimoida sitä itse. Eli esimerkiksi voi auttaa joku muuttuja, josta löytyy jo lasketut ratkaisut. Sitten jos ratkaisu löytyy sieltä voi palauttaa sen suoraan ja katkaista rekursion. (Tietty tämä ei auto jos rekursio ei mene edes kertaa loppuun). Rekursion saattaa myös voida helpostikin muuttaa iteratiiviseksi.

kyyhky89 [09.09.2019 18:53:33]

Lainaa #

Kiitos neuvoista. Minä ehkä ilmaisen itseäni hieman huonosti, pahoitteluni. Tarkoitin siis alunperin seuraavaa. Suoritan ohjelmaani ja Python 3.7.3 Shelliin tulee ilmoitus virheestä. Kuinka voisin saada tästä virheestä näkyvän ilmoituksen ohjelman suorituksen aikana. Vaikka virhe tapahtuu missä kohtaa tahansa, niin haluaisin saada siitä tiedon samalla hetkellä kuin tuo teksi Shelliin ilmestyy. Voi olla, että se ei ole mahdollista, minä en tiedä? Olen ihan pöhkö harrastelija ja siksi näitä tyhmiä kysymyksiä kyselen:-)

Metabolix [09.09.2019 19:57:28]

Lainaa #

No niin, eli ongelma ei olekaan virheen mystinen katoaminen vaan yksinkertaisesti se, miten tavallinen virheilmoitus havaitaan ja näytetään ohjelman graafisessa käyttöliittymässä.

Virheilmoituksen Traceback-listasta selviää, missä virhe tapahtuu ja miten siihen kohtaan ohjelmaa on päädytty.

Traceback (most recent call last):
  File "ohjelma.py", line 7, in <module>
    bugikoodi()
  File "ohjelma.py", line 3, in bugikoodi
    raise ValueError("Virheellinen arvo!")

Esimerkiksi yllä selviää, että virhe aiheutuu funktiossa nimeltä bugikoodi ja että kyseistä funktiota on kutsuttu ohjelma.py-tiedoston riviltä 7.

Virheen aiheuttavan koodin voi laittaa try-lohkoon, ja sen jälkeen voi tehdä except-lohkon, jossa virheilmoitus näytetään.

def bugikoodi():
  # Tässä koodissa tapahtuu virhe.
  raise ValueError("Virheellinen arvo!")

# Tässä osataan odottaa virhettä ja käsitellään se sitten.
try:
  bugikoodi()
except Exception as virhe:
  # Näytetään virheilmoitus.
  print("Nyt kävi köpelösti: " + str(virhe))
  # Virheen voi myös heittää eteenpäin, jolloin se siirtyy seuraavaan
  # (eli ulompaan) try-lohkoon tai viime kädessä tulostuu konsoliin.
  raise

Yllä olevaan esimerkkiin voi print-rivin tilalle laittaa jotain muuta koodia, jolla virheen saa näytettyä sopivalla tavalla sopivassa paikassa.

kyyhky89 [11.10.2019 13:20:56]

Lainaa #

Kiitos sinulle. Siis minun pitää rakentaa tällainen koodi jokaiseen aliohjelmaan, missä vika voi tulla esiin. Olisin toivonut sellaista ohjelman pätkää, mikä kertoo virheestä missä vain ohjelman suorituksen aikana. Siis näytölle tulisi ilmoitus, että virhe, selvitä syy! En ole saanut pitkään aikaan virheilmoituksia, mutta tiedän sellaisia voivan joskus tulla ja silloin voi käydä niin, että jokin tieto ei esim tallennu, enkä tiedä siitä yhtään mitään, kun en katso erikseen shelliin.

Grez [11.10.2019 15:51:26]

Lainaa #

Kyllähän sen shelliin tulevan virheilmoituksen varmasti saa tulemaan jonnekin muuallekin, ilman että jokaista aliohjelmaa tarvitsee muuttaa. Nyt vaan kukaan muu kuin sinä ei tiedä minne sen ilmoituksen pitäisi tulla. Rivien välistä voi tavallaan lukea että sinulla saattaa olla joku graafinen käyttöliittymä, jonka olet tehnyt jollain Pythonin useista kymmenistä graafisen käyttöliittymän kirjastoista, mutta tätä pidemmälle on paha arvailla.

Yleisesti ottaen voisin kuvitella että samalla tekniikalla miten tässä opastetaan kirjoittamaan virheet lokiin, voisi myös näyttää ne missä haluaa:
https://doughellmann.com/blog/2009/06/19/python-exception-handling-techniques/


Sivun alkuun

Vastaus

Muista lukea kirjoitusohjeet.
Tietoa sivustosta