Input auf Zahlen prüfen/nur Zahlen erlauben

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Benutzeravatar
schurli
User
Beiträge: 2
Registriert: Sonntag 17. Oktober 2021, 17:40

Hallo zusammen,

ich bin seit einiger Zeit dabei in die Welt von python einzutauchen und finde immer mehr Gefallen daran. Heute beschäftige ich mich schon den ganzen Tag mit if, while und input eingaben. Bei meine Programm soll eine Zahl zwischen 1 und 100 eingeben werden. Die Überprüfung des Bereichs funktioniert ja schon mal. Aber wenn man Buchstaben eingibt brichts das Programm ab. Ich hab mir schon die Finger wund gegoogelt und auch einiges gefunden wie ich das Feld überprüfen kann, bekomme aber immer nur Fehler und Programmabbruch. Das mit den strings und integer etc ist mir noch ein wenig unklar. Naja Übung macht den Meister. Für eine Denkanstoss und Erklärung wäre ich sehr dankbar.

Code: Alles auswählen

        if c_ip is True and start == '8':
            print('Gib die gewünschte Zahl zwischen 1 und 100 an:')
            zahl1 = int(input())
            while zahl1 > 100:
                print('Eingabe muss zwischen 1 und 100 liegen und darf nur Text sein.')
                zahl1 = int(input())
            print('\nDanke. Los geht es...\n')            
            os.system(zahl2 + str(zahl1) + ' ' + wert1)
            nextone()
100% python noob.
Benutzeravatar
sparrow
User
Beiträge: 4540
Registriert: Freitag 17. April 2009, 10:28

Gewöhn dir erst gar nicht an, kryptische Abkürzungen zu verwenden. Niemand weiß, was "c_ip" bedeutet. Auch du in 4 Tagen nicht mehr.

Deine Prüfung der Eingabe ist falsch. Du prüfst nur, ob die Zahl größer als 100 ist. Was ist, wenn jemand 0 oder -50 eingibt?
Statt zu prüfen ob die Zahl größer als 100 ist und dann darauf zu reagieren, solltest den korrekten Bereich prüfen und nur dann fortsetzen: 0 < eingabe <= 100

Warum nummerierst du Variablen durch? Wenn man das tut, will man eigentlich eine Liste verwenden.

Wo kommen denn zahl2 und wert1 her? Warum sind die nummeriert?

Was soll der Aufruf von os.system? Warum willst du dort einen Systembefehl ausführen, der aus den Werten zusammgesetzt ist? Ist das wirklich so gewollt?
Zeichenketten setzt man nicht mit + zusammen sondenr verwendet String-Formatierung. Stichwort f-Strings.

"nextone" sieht verdächtig so aus, als würdest du Funktionen als Sprungmarken verwenden. Wenn dem so ist, dann ist das falsch.


Zu deiner Frage: Du musst den Fehler (und zwar nur den erwarteten Fehler!) der Falscheingabe abfangen. Stichwort: try except
Sirius3
User
Beiträge: 18276
Registriert: Sonntag 21. Oktober 2012, 17:20

Der Vergleich mit is ist falsch. Woher kommen c_ip und start?
Man vermeidet Code-Wiederholungen. Es sollte nur einen input-Aufruf geben.
Fehler fängt man mit try ab.
Welches Programm besteht denn aus zwei zusammengesetzten Zahlen?
os.system benutzt man auch nicht, sondern subprocess.run.

Code: Alles auswählen

if c_ip and start == '8':
    print('Gib die gewünschte Zahl zwischen 1 und 100 an:')
    while True:
        try:
            zahl1 = int(input())
            if 1 <= zahl1 <= 100:
                break
        except ValueError:
            pass
        print('Eingabe muss zwischen 1 und 100 liegen und darf nur Text sein.')
    print('\nDanke. Los geht es...\n')  
    subprocess.run([f"{zahl2}{zahl1}", wert1])
    nextone()
Benutzeravatar
__blackjack__
User
Beiträge: 14069
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@schurli: Wandel einfach in eine Zahl um und behandle dabei eventuell auftretende Ausnahmen entsprechend. Anmerkungen zum Quelltext:

Verwende keine kryptischen Abkürzungen, nichtssagende Namen, und keine Namen an die Nummern angehängt sind. Namen sollen dem Leser vermitteln was der Wert bedeutet; die sind wichtig. Man sollte nicht rätseln müssen was `c_ip` bedeuten mag oder was es für einen Sinn macht eine Zeichenkette `zahl2` zu nennen und wieso das der Name eines ausführbaren Shell-Kommandos oder eines Programms ist.

Wahrheitswerte vergleicht man nicht mit ``is`` und in diesem Fall vergleicht man das mit gar nichts. Da kommt doch nur wieder ein Wahrheitswert bei heraus. In diesem Fall der gleiche den man mit `c_ip` sowieso schon hatte, und den man deswegen auch gleich selbst verwenden kann.

Den Prompt kann man `input()` als Argument übergeben, da braucht man kein Extra-`print()`.

`os.system()` sollte man nicht verwenden. Die Dokumentation verweist auf das `subprocess`-Modul.

Damit fällt auch ein Teil des zusammenstückelns von Zeichenketten und Werten mittels ``+`` und `str()` weg, was man in Python nicht macht. Dafür gibt es f-Zeichenkettenliterale. Und der andere Teil entfällt, weil man bei `subprocess.run()` die einzelnen Bestandteile nicht zu einer Zeichenkette zusammensetzt, die danach dann ja sowieso nur wieder von der Shell in Einzelteile zerlegt würden.

Bei `nextone()` fehlt ein Unterstrich zwischen den Worten: `next_one()`. Ist aber auch kein guter Funktionsname, denn die beschreiben in der Regel die Tätigkeit, die von der Funktion verrichtet wird.

Und wegen dem Anfängerstatus drängt sich bei der Funktion mit dem Namen so ein bisschen der Verdacht auf, dass da was falsch gemacht wird: rekursive Funktionsaufrufe dürfen nicht als missbrauch für Schleifen verwendet werden. Das skaliert nicht und führt irgendwann zu einer Ausnahme.

Ungetestet:

Code: Alles auswählen

        if c_ip and start == "8":
            print("Gib die gewünschte Zahl zwischen 1 und 100 an:")
            while True:
                try:
                    zahl = int(input())
                    if 1 <= zahl <= 100:
                        break
                except ValueError:
                    pass
                
                print("Eingabe muss zwischen 1 und 100 liegen und darf nur Text sein.")
                
            print("\nDanke. Los geht es...\n")            
            subprocess.run([f"{zahl2}{zahl}", wert1], check=True)
            next_one()
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Benutzeravatar
schurli
User
Beiträge: 2
Registriert: Sonntag 17. Oktober 2021, 17:40

Guten Abend,

danke mal für die schnellen, zahlreichen Antworten und Tipps. Viel Input... puh. :roll:

Also ich wollte nicht den ganzen Code posten. Das wären 186 Zeilen gewesen, das ist nur ein Ausschnitt. Ich dachte das reicht, ich hätte das aber anders benennen sollen. sorry.
Der Vergleich mit is ist falsch. Woher kommen c_ip und start?
Man vermeidet Code-Wiederholungen. Es sollte nur einen input-Aufruf geben.
Fehler fängt man mit try ab.
Welches Programm besteht denn aus zwei zusammengesetzten Zahlen?
os.system benutzt man auch nicht, sondern subprocess.run.
Sinn des Programms ist das ich mir gewisse Netzwerkbefehle die ich im Terminal ausführe und die viele Optionen haben in einem Tool für mich zusammenfasse. Quasi ein kleiner Werkzeugkasten. Dann eben durch einfach Auswahl der Nummer in meinem Menü + Eingabe IP Adresse + eventuell Portnummer + eventuell IP Adressbereich usw. den jeweiligen Befehl starte.

Zum Beispiel: ping -I eth0 -s 100000 192.168.1.94
Gewöhn dir erst gar nicht an, kryptische Abkürzungen zu verwenden. Niemand weiß, was "c_ip" bedeutet. Auch du in 4 Tagen nicht mehr.
Das cp_ip kommt von c_ip = iptools.ipv4.validate_ip(ip) das mir prüft ob es eine gültige IP Adresse ist. Aber du hast sicher recht, das ist keine Gute Idee, Danke.
Warum nummerierst du Variablen durch? Wenn man das tut, will man eigentlich eine Liste verwenden.
Im richtigen Code haben die Variablen einen eindeutigen Namen. Das hab ich nur für den gekürzten Code geändert den ich hier gepostet habe.
Was soll der Aufruf von os.system? Warum willst du dort einen Systembefehl ausführen, der aus den Werten zusammgesetzt ist? Ist das wirklich so gewollt?
Zeichenketten setzt man nicht mit + zusammen sondenr verwendet String-Formatierung. Stichwort f-Strings.
Ja das ist so gewollt, da hier unterschiedliche Befehle ausgeführt werden die ich in Variablen gespeichert habe. f-Strings kenn ich nicht, werde ich mir mal zu Gemüte führen. Danke!
"nextone" sieht verdächtig so aus, als würdest du Funktionen als Sprungmarken verwenden. Wenn dem so ist, dann ist das falsch.
Wenn ich dich richtig verstehe dann mache ich das Falsch ja. Ja es ist quasi eine Sprungmarke die sagt... Befehl ausgeführt, enter drücken für menü und dann kommt das Menü wieder.
Den Prompt kann man `input()` als Argument übergeben, da braucht man kein Extra-`print()`.
ok, danke. Hab ich nicht gewusst.
`os.system()` sollte man nicht verwenden. Die Dokumentation verweist auf das `subprocess`-Modul.
Da hab ich bei der Google Suche immer beides gefunden zum Aufruf. Danke für den Hinweis. In Zukunft also subprocess.
Damit fällt auch ein Teil des zusammenstückelns von Zeichenketten und Werten mittels ``+`` und `str()` weg, was man in Python nicht macht. Dafür gibt es f-Zeichenkettenliterale. Und der andere Teil entfällt, weil man bei `subprocess.run()` die einzelnen Bestandteile nicht zu einer Zeichenkette zusammensetzt, die danach dann ja sowieso nur wieder von der Shell in Einzelteile zerlegt würden.
Die Umwandlung in str habe ich gemacht weil python gemeckert hat das er das eben nicht mit + zusammenbauen kann. Das + erschien mir irgendwie logisch um die einzelnen Teile zu verknüpfen. Also zum Beispiel.. Setze zusammen "Befehl mit Optionen" + "Datenmenge" + "Portnummer" + "IP Adresse"

Und wegen dem Anfängerstatus drängt sich bei der Funktion mit dem Namen so ein bisschen der Verdacht auf, dass da was falsch gemacht wird: rekursive Funktionsaufrufe dürfen nicht als missbrauch für Schleifen verwendet werden. Das skaliert nicht und führt irgendwann zu einer Ausnahme.
Ich versteh nur Bahnhof. :lol: Aber danke ich hoffe das werde ich bald verstehen was du da meinst.

@blackjack - Danke für deine Mühe. Sieht schon mal gut aus. Ich bekomme noch einen Fehler beim subprocess. Aber ich weiß wo ich ansetzen muss.
100% python noob.
Antworten