andie39‘s Fragen Thread

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.
Benutzeravatar
andie39
User
Beiträge: 152
Registriert: Dienstag 7. Dezember 2021, 16:32

Sirius3 hat geschrieben: Donnerstag 13. Januar 2022, 20:09 Das willst Du doch, alle Zeilen durchgehen, und prüfen, ob in irgendeiner Zeile Dein Filmtitel steht.
Und wenn die Datei bis zum Ende durchsucht worden ist, hört die Schleife automatisch auf.

Ja. Aber bei meinem Code endet die Suche ja nicht oder?
Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

Woran siehst Du, dass die Suche nicht endet?
Benutzeravatar
andie39
User
Beiträge: 152
Registriert: Dienstag 7. Dezember 2021, 16:32

Sirius3 hat geschrieben: Donnerstag 13. Januar 2022, 20:37 Woran siehst Du, dass die Suche nicht endet?
Im Jupyter Notebook erschein ein * das für eine Endlosschleife steht.

Ich habe es jetzt einmal ähnlich deinem probiert:

Code: Alles auswählen


def add_movie():
    with open ("movies.csv", "r+") as file:
        eingabe = input("Geben Sie einen Filmtitel ein:")
        if eingabe in file:       
            print("Titel schon vorhanden")
        else:  
            file.write(eingabe + "\n")
            
Hier wird ein Titel immer hinzugefügt, ist der Titel schon vorhanden passiert das immer noch.
Also if eingabe in file funktioniert so also nicht.
Benutzeravatar
__blackjack__
User
Beiträge: 13061
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@andie39: Mit der Endlosschleife hat hier keiner so wirklich gerechnet weil wir kaum Erfahrungen mit "r+" als Dateimodus haben, weil das keiner macht. Das produziert hier natürlich tatsächlich eine Endlosschleife weil Du die Datei ja in jedem Schleifendurchlauf um eine Zeile erweiterst, die dann im nächsten Schleifendurchlauf gelesen wird, in dem dann die Datei wieder um eine Zeile erweitert wird, und dass dann "unendlich". Solange bis die Platte voll ist, was bei heutigen Plattengrössen eine Weile dauern könnte. 😀

Erst einmal das ganz grundsätzlich eine Schleife über die Zeilen endet wenn die Zeilen alle gelesen wurden, einmal tatsächlich als Schleife und dann was passiert wenn man den Iterator wiederholt nach dem nächsten Element fragt:

Code: Alles auswählen

In [22]: !cat movies.csv                                                        
Love actually
Die Hard
The Grinch

In [23]: file = open("movies.csv")                                              

In [24]: for movie_name in file: 
    ...:     print(movie_name) 
    ...:                                                                        
Love actually

Die Hard

The Grinch


In [25]: file.close()                                                           

In [26]: file = open("movies.csv")                                              

In [27]: next(file)                                                             
Out[27]: 'Love actually\n'

In [28]: next(file)                                                             
Out[28]: 'Die Hard\n'

In [29]: next(file)                                                             
Out[29]: 'The Grinch\n'

In [30]: next(file)                                                             
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-30-0f391ff92824> in <module>
----> 1 next(file)

StopIteration:
Und jetzt das der ``in``-Operator den Iterator komplett durchgeht:

Code: Alles auswählen

In [32]: file = open("movies.csv")                                              

In [33]: 'something' in file                                                    
Out[33]: False

In [34]: next(file)                                                             
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-34-0f391ff92824> in <module>
----> 1 next(file)

StopIteration: 

In [35]: file.close()                                                           
Nach dem ``in`` kann man keine Zeilen mehr von `file` bekommen, weil die für den Test schon alle ”verbraucht” wurden.

Zur Kodierung: Dann hast Du doch sogar schon ein praktisches Beispiel warum die Kodierungsangabe *wichtig* ist, und die weg zu lassen ein *Fehler*. Wenn Du UTF-8 explizit angibst, dann funktioniert das unter Windows *und* auf dem IPad. Ohne kannst Du die Daten zwischen den beiden Systemen nicht austauschen, sofern die Texte sich nicht auf ASCII beschränken. Und selbst das kann dann auf Systemen Probleme machen, bei denen eine Kodierung eingestellt ist, die ASCII nicht als Untermenge hat. Keine Ahnung wie weit so etwas beispielsweise im asiatischen oder arabischen Raum verbreitet ist.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
andie39
User
Beiträge: 152
Registriert: Dienstag 7. Dezember 2021, 16:32

Ja das mit der Codierung hattet ihr mir neulich ja dargelegt :)

Hier geht es mir aber gerade darum:
Wie kann ich denn nun die Datei durchsuchen ob die Eingabe schon vorhanden ist ohne das die Schleife ewig läuft oder das in alles verbraucht?
Bzw das verstehe ich nicht, ich prüfe ja erst ob die die Eingabe in der Datei ist. Aber selbst wenn das der Fall ist, gibt er nicht die Meldung aus. Er fügt immer wieder Filme hinzu auch wenn die schon vorhanden sind.
Benutzeravatar
__blackjack__
User
Beiträge: 13061
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@andie39: Du prüfst nicht ob der Film schon in der Datei ist weil in der Datei Werte sind die mit einem Zeilenendezeichen enden, die Eingabe die Du da suchst aber nicht, also so wie das geschrieben ist, kann der Test niemals wahr sein. Noch mal die Beispieldatei aus meinem letzten Beitrag und der Benutzer hat "Die Hard" eingegeben, was ja ein Film in der Datei ist, aber der Wert "Die Hard" kommt so nicht als Element/Zeile in der Datei vor:

Code: Alles auswählen

In [38]: !cat movies.csv                                                        
Love actually
Die Hard
The Grinch

In [39]: file = open("movies.csv")                                              

In [40]: "Die Hard" in file                                                     
Out[40]: False
Wenn man sich anschaut was die Elemente in der Datei sind:

Code: Alles auswählen

In [41]: file = open("movies.csv")                                              

In [42]: next(file)                                                             
Out[42]: 'Love actually\n'

In [43]: next(file)                                                             
Out[43]: 'Die Hard\n'

In [44]: next(file)                                                             
Out[44]: 'The Grinch\n'

In [45]: next(file)                                                             
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-45-0f391ff92824> in <module>
----> 1 next(file)

StopIteration: 
Da ist tatsächlich kein "Die Hard" dabei sondern "Die Hard\n" was halt bei einem Vergleich ungleich ist. Dazu müsste man entweder an den gesuchten Wert das Zeilenendezeichen anhängen, oder bei den Zeilen das Zeilenendezeichen entfernen für den Test:

Code: Alles auswählen

In [46]: file = open("movies.csv")                                              

In [47]: "Die Hard\n" in file                                                   
Out[47]: True

In [48]: file = open("movies.csv")                                              

In [49]: "Die Hard" in (line.rstrip() for line in file)                         
Out[49]: True
Dein ursprünglicher Code hätte dann immer noch ein Problem mit der ``for``-Schleife, selbst wenn die nur lesend wäre: die konsumiert vor dem Test die erste Zeile der Datei, dass heisst den ersten Film könnte man auch dann nicht finden, wenn man das Zeilenendezeichen beim Test berücksichtigt.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

Das mit der Endlosschleife habe ich schon getestet. Beim Schreiben wird der Filepointer ja ans Ende des geschriebenen Textes gesetzt, so dass dann nichts mehr gelesen werden kann, es darf also eigentlich keine Endlossschleife geben. Aber vielleicht macht da Windows irgendwelches Woodoo.

@andie39: Du machst ja auch nicht das, was geschrieben habe. Das muß schon exakt so sein. Es kommt auf die Details an. 'r+' darf man wirklich nicht benutzen.
Benutzeravatar
andie39
User
Beiträge: 152
Registriert: Dienstag 7. Dezember 2021, 16:32

Also ich eine Lesen und eine Schreibenfunktion.
Erst also dann die Funktion lesen und prüfen lassen und wenn die schief läuft die Schreibenfunktion?
Aber wie würde die lesen und prüfen Funktion aussehen damit diese funktioniert?
Benutzeravatar
andie39
User
Beiträge: 152
Registriert: Dienstag 7. Dezember 2021, 16:32

Ich habe mal folgendes gefunden:

1. Verwenden Sie die Methode File readlines(), um eine Zeichenkette in einer Datei in Python zu finden
2. Verwenden der Methode file read() zum Suchen einer Zeichenkette in einer Datei in Python
3. Verwenden der Methode find zum Suchen einer Zeichenkette in einer Datei in Python
4. Verwenden des Moduls mmap zum Suchen einer Zeichenkette in einer Datei in Python

Vielleicht funktioniert das besser?
Und ich umgehe die Schleife etc

Also mit read eine Liste machen und die durchsuchen mit der for -Schleife das werde ich probieren
Benutzeravatar
andie39
User
Beiträge: 152
Registriert: Dienstag 7. Dezember 2021, 16:32

Es funktioniert, ja ich weiss es ist noch immer r+
aber es funktioniert

Code: Alles auswählen


def add_movie():
    with open ("movies.csv", "r+") as file:
        eingabe = input("Geben Sie einen Filmtitel ein:")
        if eingabe in file.read():       
            print("Titel schon vorhanden")
    
        elif eingabe not in file:  
            file.write(eingabe + "\n")
   
Benutzeravatar
Dennis89
User
Beiträge: 1152
Registriert: Freitag 11. Dezember 2020, 15:13

Hallo,

dann kannst du im nächsten Schritt das 'r+' rauswerfen und die Tipps einbauen die man dir genannt hat.
Falls du mal mit "richtig" mit CSV-Dateien arbeiten willst, es auch ein csv-Modul in Python:
https://docs.python.org/3/library/csv.html

Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Benutzeravatar
andie39
User
Beiträge: 152
Registriert: Dienstag 7. Dezember 2021, 16:32

Ja das werde ich machen.

Ich habe das bei der Entfernenfunktion auch schon gemacht.
Beide sollen aber noch angepasst werden, dass man mehr hinzufügen kann.

Aber erstmal funktionieren beide hier die entfernen Funktion:

Code: Alles auswählen

def remove_movie():
    with open("movies.csv", "r") as file:
        lines = file.readlines()
    with open("movies.csv", "w") as file:
        eingabe = input("Welchen Film möchten Sie enternen?")
        for element in lines:
            if element != eingabe + ("\n"):
                file.write(element)
               
Benutzeravatar
__blackjack__
User
Beiträge: 13061
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@andie39: Das funktioniert so nicht. Du kannst nicht die ganze Datei einfach als *eine* Zeichenkette betrachten und darin dann darauf reagieren ob *irgendwo* die `eingabe` als Teilzeichenkette vorkommt. Weil man dann keinen Film mehr eintragen kann dessen Name ein *Teil* eines bereits vorhandenen Films ist.

Und der ``elif``-Teil macht keinen Sinn, weil dies Bedingung *immer* ``False`` ist. Man muss keine Bedingung prüfen von der man grundsätzlich das Ergebnis vorher kennt.

Wie ”real” soll das Szenario eigentlich sein, dass hier abgebildet wird? Denn es gibt ja durchaus unterschiedliche Filme, die den gleichen Titel haben.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
andie39
User
Beiträge: 152
Registriert: Dienstag 7. Dezember 2021, 16:32

@blackjack:

Wieso soll die immer false sein?
Er prüft ob der Titel vorkommt und wenn nicht, dann fügt er den Film hinzu.
Benutzeravatar
sparrow
User
Beiträge: 4183
Registriert: Freitag 17. April 2009, 10:28

Welcher Fall soll denn eintreten, damit die Bedingung hinter dem elif erreicht wird und nach Auswertung nicht True sein könnte. Wenn man das Gegenteil einer Bedingung ohne weitere Bedingung hat, benutzt man else .

Wenn die Bedingung machen würde was sie soll. In deinem Fall ist die Bedingung nach dem elif aber immer False. Du prüft nicht, was du denkst. Probier es doch mal aus.
Benutzeravatar
andie39
User
Beiträge: 152
Registriert: Dienstag 7. Dezember 2021, 16:32

Else war für mich auch logisch aber else geht nicht da gab es einen Fehler.
Warum ist mir nicht klar.
Mir elif wird geprüft und wenn nicht vorhanden der Film hinzugefügt.
Benutzeravatar
sparrow
User
Beiträge: 4183
Registriert: Freitag 17. April 2009, 10:28

Das mit dem Fehler, der jetzt nicht mehr kommt, könnte daran liegen, dass der elif Zweig nie ausgeführt wird. Die Bedingung ist immer False.

Probier doch mal aus ob "irgendwas" in file jemals True sein kann.
Benutzeravatar
andie39
User
Beiträge: 152
Registriert: Dienstag 7. Dezember 2021, 16:32

Wieso wird der elif nicht ausgeführt ich verstehe es grad echt nicht. Er macht doch erst die erste Abfrage ob die true ist und danach die elif.
Wenn der Film schon drin ist meldet er das sonst fügt er den hinzu.
Ich stimme zu eigentlich sollte er if… und else machen sind ja nur true oder false.

Aber funktionieren tut es ja meine ich. Bin nicht am PC gerade aber gestern hat es meine ich korrekt funktioniert.
Benutzeravatar
andie39
User
Beiträge: 152
Registriert: Dienstag 7. Dezember 2021, 16:32

Ansonsten wäre mein Gedanke das man es so wie jetzt macht aber noch:

else:
assert false

einbaut
Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

Zu Deinem Code

Code: Alles auswählen

def add_movie():
    with open ("movies.csv", "r+") as file:
        eingabe = input("Geben Sie einen Filmtitel ein:")
        if eingabe in file.read():       
            print("Titel schon vorhanden")
    
        elif eingabe not in file:  
            file.write(eingabe + "\n")
Wie ich schon schrieb, ist `eingabe` ohne Zeile-Ende-Zeichen niemals in den Zeilen einer Datei. Daher ist die Abfrage `eingabe not in file` immer wahr.
Zweiter Grund ist, dass Du mit `file.read()` bereits die gesamte Datei gelesen hast, also `file` sofort mit StopIteration abbricht, und deshalb `not in` immer wahr ist.
Daher kann man das elif durch ein viel einfacheres `else` ersetzen, was auch logisch viel sinnvoller ist, denn sonst müßte man sich Gedanken machen, was diese Abfrage eigentlich soll.

Als nächstes ist `eingabe in file.read()` falsch, denn wenn Du schon den Film "Escape Room" eingetragen hast, kannst Du nicht mehr "Es" eintragen, weil das schon als Teilstring im ersten Film enthalten ist.
Antworten