• 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

0 głosów
112 wizyt
pytanie zadane 4 czerwca w Python, Django przez Ventre90 Użytkownik (670 p.)
zamknięte 6 czerwca 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 przez mrspock1 Mądrala (5,120 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 przez Ventre90 Użytkownik (670 p.)
Tak to program konsolowy. Rezultaty o których pisałem są z PowerShella.

3 odpowiedzi

+1 głos
odpowiedź 4 czerwca przez mokrowski VIP (112,700 p.)
wybrane 6 czerwca 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 przez adrian17 Ekspert (204,380 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 przez Ventre90 Użytkownik (670 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 przez mokrowski VIP (112,700 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 przez Ventre90 Użytkownik (670 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 przez mokrowski VIP (112,700 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 przez Ventre90 Użytkownik (670 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ź 166 wizyt
0 głosów
1 odpowiedź 151 wizyt
0 głosów
1 odpowiedź 154 wizyt
Porady nie od parady
Komentarze do pytań nie służą do odpowiadania, od tego jest wydzielona sekcja odpowiedzi. Funkcją komentarzy jest natomiast możliwość uzyskania dodatkowych informacji na temat samego posta.Komentarze

67,143 zapytań

114,088 odpowiedzi

241,831 komentarzy

47,039 pasjonatów

Przeglądających: 252
Pasjonatów: 11 Gości: 241

Motyw:

Akcja Pajacyk

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

Oto dwie polecane książki warte uwagi. Pełną listę znajdziesz tutaj.

...