• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

question-closed Zabezpieczenie programu przed wprowadzeniem STR (przeciwdziałanie CRASHOWI) - Python

Konkurs Mistrz Programowania
0 głosów
2,309 wizyt
pytanie zadane 4 czerwca 2019 w Python przez Ventre90 Obywatel (1,170 p.)
zamknięte 6 czerwca 2019 przez Ventre90

Cześć drodzy pasjonaci. Mam do Was pytanie odnośnie zabezpieczania programów przed wprowadzeniem przez użytkownika tzw ,,Invalid Input" w postaci string, co skutkuje ValueErrorem i wykrzaczeniem programu, w sytuacji kiedy program wymaga wprowadzenie np: zmiennych typu INT. Szczególnie w przypadkach gdy program ma dalej coś policzyć na podstawie zmiennych int. Poniżej wkleiłem 2 krótkie kody gdzie starałem się wymyślić jak uniknąć ,,crashu" na skutek błędnego wprowadzenia zmiennej string. 

Czy istnieje możliwość zabezpieczenia programu tylko za pomocą komend try: / except, bez konieczności wprowadzania jakiejś dodatkowej ,,logiki zabezpieczającej w postaci IFów lub/i pętli.

1. To program który losuje liczbę od 1-100 i daje 5 szans na odgadnięcie. Pomimo, że zabezpieczyłem try/except przy wprowadzaniu zmiennych to i tak mi go wywalało gdy program dochodził do momentu określenia czy liczba jest większa / mniejsza od wprowadzonej ( if x > num:). Dodałem więc ifa na sprawdzenie typu zmiennej (chyba to tak działa) no i nie wykrzacza się. Jednak mam wątpliwości czy jest to rozwiązanie optymalne i czy nie da się tego zrobić samym try / except ?

x = random.randint(1,100)

num = ""
chance = 0

while x != num and chance != 5:

    chance += 1
    chan_rate = 5 - chance

    try:
        num = int(input("Wprowadz liczbę: "))
    except ValueError as err:
        print("Wprowadź liczbę!", err)


    if x == num:
        print ("BRAWO WYGRYWASZ !!!")
        break
                
    if chance < 5:
        print("Dostępne Szanse: {}" .format(chan_rate))

        if num:
            if x > num:
                print("Wylosowana Liczba jest większa. Próbuj dalej.")
            else:
                print("Wylosowana liczba jest mniejsza. Próbuj dalej.")
        elif not num:
            print("Podaj liczbę całkowitą! - ValueError.")
    else:
        print("BRAK SZANS.")

if x != num:
    print("PRZEGRANA !!! Komputer wylosowal: {}" . format (x))

2 program na spełnianie warunków budowy trójkąta / wyznaczenie trójkąta pitagorejskiego. Tutaj z try / except mi kompletnie nie wychodziło, bo z racji tego ze są 3 zmienne to program zawsze sie gdzieś wykrzaczył, a nawet jak nie to zamykał się po wyświetleniu komunikatu błędu, bez poproszenia o kolejny Input. Zbudowałem więc taką pętle while i teoretycznie działa. Znów rodzi się pytanie czy to nie powinno być zrobione samym try / exceptem.

a = ""
b = ""
c = ""

while not a or not b or not c:
    try:
        a = int(input("Podaj bok pierwszy: "))
        b = int(input("Podaj bok drugi: "))
        c = int(input("Podaj bok trzeci: "))
    except ValueError as err:
        print("Wprowadzaj TYLKO liczby CAŁKOWITE!")
    

if c < a: # mozna to zrobic tez ze zmienną. ('temp')
     c,a = a,c
if c < b:
    c,b = b,c
if b < a:
    b,a = a,b

print (a , b, c)


if (a + b > c):
    print("Trójkąt jest mozliwy")
    trigle = True
else:
    print("Z tych bokow NIE bedzie Trójkąta")
    trigle = False

if (trigle and a**2 + b**2 == c**2):
    print("Trójkąt Pitagorejski.")
    if ( a/3 == b/4 == c/5):
        print("Trójkąt Egipski")
elif(trigle):
    print("Trójkąt NIE Pitagorejski"

PS. Przepraszam za długi wątek ale staram się uczyć kodowania z przyzwoitymi standardami i zabezpieczać programy przed crashem w taki sposób jak przychodzi mi to do głowy.

Pozdrawiam i dzięki za wyrozumiałość.

komentarz zamknięcia: Rozwiązanie tematu.
komentarz 4 czerwca 2019 przez mrspock1 Mądrala (6,420 p.)
To chyba program konsolowy bez GUI? Bo inaczej pętla nie byłaby potrzebna. Myślałem że programy konsolowe przestały być robione wiele lat temu.
komentarz 5 czerwca 2019 przez Ventre90 Obywatel (1,170 p.)
Tak to program konsolowy. Rezultaty o których pisałem są z PowerShella.

3 odpowiedzi

+1 głos
odpowiedź 4 czerwca 2019 przez mokrowski Mędrzec (158,940 p.)
wybrane 6 czerwca 2019 przez Ventre90
 
Najlepsza
#!/usr/bin/env python3

def read_int(prompt, err_msg):
    while True:
        try:
            value = int(input(prompt))
            return value
        except ValueError as e:
            print(err_msg)
        else:
            return value

if __name__ == '__main__':
    value = read_int("Wprowadź liczbę: ", "Nieprawidłowe dane, spróbuj jeszcze raz")

 

0 głosów
odpowiedź 4 czerwca 2019 przez adrian17 Mentor (354,880 p.)

Bez pętli się nie da.

Najprościej pewnie powtarzać pętlę, póki parsowanie się nie udaje, czyli coś w stylu:

while True:
    try:
        a = int(input("Podaj bok pierwszy: "))
        b = int(input("Podaj bok drugi: "))
        c = int(input("Podaj bok trzeci: "))
        break
    except ValueError as err:
        print("Wprowadzaj TYLKO liczby CAŁKOWITE!")
        continue

Można by też całą tą logikę wyrzucić do funkcji, gdyby ten kod się powtarzał.

0 głosów
odpowiedź 5 czerwca 2019 przez Ventre90 Obywatel (1,170 p.)

adrian17 i mokrowski, przede wszystkim serdecznie dziękuje za odpowiedzi. Obie bardzo mi pomogły.

@Adrian - dzieki za ten pomysł z continue. Teraz to powstawiałem, kod jest bardziej czytelny i wszystko hula. Dzięki!

@Mokrowski - Dziękuję za ten pomysł z 2 parametrami w funkcji. nie pomyślałem o tym. To wiele ułatwia i jest super rozwiązaniem. Czy możesz mi jednak wyjaśnić o co chodzi z zapisem:

if __name__ == '__main__':

Dowiedziałem się, że to coś związane z modułami, że rozpoznaje jakieś zmienne w kodzie, czy coś i wykonuje jakiś blok funkcji. Generalnie nic z tego nie rozumiem. Czy możesz lub ktokolwiek inny mógłby, wyjaśnić to łopatologicznie - co to robi, do czego się przydaje i do czego się to używa.

PS. Jak wyhaszowałem tą linijkę z tym if-em, z napisanego przez ciebie kodu, to to zabezpieczanie dalej działa jak należy.

komentarz 5 czerwca 2019 przez mokrowski Mędrzec (158,940 p.)
Każdy program/skrypt w języku Python może działać w 2 trybach:

1. Jako samodzielny program.

2. Jako moduł.

W trakcie uruchamiania skryptu jako samodzielny program, zmienna __name__ (dwa podkreślniki name dwa podkreślniki), ma wartość '__main__' (dwa podkreślniki main dwa podkreślniki). Jeśli skrypt wczytujesz jako moduł, name ma wartość taką jak nazwa modułu. W ten sposób tworzysz poprawne i kontrolowane wejście do skryptu w tym języku a jednocześnie pozwalasz w przyszłości wczytać skrypt jako moduł.

Często ta sekcja służy także do uruchamiania testów modułu.
komentarz 5 czerwca 2019 przez Ventre90 Obywatel (1,170 p.)
Ok nie powiem ze jest to dla mnie całkowicie jasne ale chociaż wiem w którym kościele dzwoni. O ile w przypadku modułów jestem w stanie sobotę wyobrazić funkcjonalność tej sekcji, to jaką ona rolę spełnia gdy skrypt jest samodzielnym programem? Jaką funkcje spełnia np. w twoim kodzie?
komentarz 5 czerwca 2019 przez mokrowski Mędrzec (158,940 p.)

Kontrolowane, jasne, 1 wejście do programu.

Dodatkowo możesz go sobie zapisać w pliku np. read_int.py i importować przez

from read_int import read_int

To jest dobra praktyka której po prostu jeszcze nie znasz.

komentarz 6 czerwca 2019 przez Ventre90 Obywatel (1,170 p.)
OK bardzo dziękuje za wyjaśnienia. Będę się starał to stosować w przyszłości.

Podobne pytania

0 głosów
1 odpowiedź 2,104 wizyt
0 głosów
1 odpowiedź 316 wizyt
+1 głos
1 odpowiedź 276 wizyt

93,656 zapytań

142,577 odpowiedzi

323,100 komentarzy

63,174 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj

Kursy INF.02 i INF.03
...