print-Anweisung zeitgleich in Tex-Widget umleiten

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.
Max77
User
Beiträge: 19
Registriert: Samstag 30. April 2016, 13:42

Code: Alles auswählen

# -*- coding: utf-8 -*-




from Tkinter import *



basisfenster = Tk()
basisfenster.title(“Hier soll Zeitgleich der gleiche Text erscheinen wie in der Python-Shell“)





schiebeleiste = Scrollbar(basisfenster)
textfenster = Text(basisfenster, height=20,width=60, font='courier 18', background='white', foreground='blue')





schiebeleiste.pack(side=RIGHT, fill=Y)
textfenster.pack(side=LEFT, fill=Y)



schiebeleiste.config(command=textfenster.yview)
textfenster.config(yscrollcommand=schiebeleiste.set)



def Text_ausgeben():

    print "Sein oder nicht sein -"

    print “ “

    print "Ob von edlem Geblüt,"

    print “ “

    print "oder nur von einfachem Gestüt."






basisfenster.after(0, Text_ausgeben())

basisfenster.mainloop()
Hallo Leute, ich suche eine Möglichkeit die Ausgaben der print-Anweisung Zeitgleich in ein Text-Widget umzuleiten. Ich habe schon per Google gesucht
aber nicht genau das Thema zu meinen Problem gefunden.

Geht das mit stdout oder subprocess und wenn ja WIE ?

Wie gesagt, die Lösungen die annähernd im WWW beschrieben werden sind sehr oft in Englisch und ich verstehe nur Bahnhof.

Ich danke im Voraus,

Max77
Zuletzt geändert von Anonymous am Sonntag 12. Juni 2016, 19:27, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@Max77: das Problem, dass Du nichts bei Google findest, ist vielleicht, dass es gar kein Problem gibt.
Du fügst das, was Du per print ausgibst einfach in Dein Text-Widget ein:

Code: Alles auswählen

# -*- coding: utf-8 -*-
import Tkinter as tk

TEXT = u"""Sein oder nicht sein -

Ob von edlem Geblüt,

oder nur von einfachem Gestüt."""

def text_ausgeben(widget, text):
    print text
    widget.insert(tk.END, text)

def main():
    basisfenster = tk.Tk()
    basisfenster.title("Hier soll Zeitgleich der gleiche Text erscheinen wie in der Python-Shell")
    schiebeleiste = tk.Scrollbar(basisfenster)
    textfenster = tk.Text(basisfenster, height=20,width=60, font='courier 18', background='white', foreground='blue')
    schiebeleiste.pack(side=tk.RIGHT, fill=tk.Y)
    textfenster.pack(side=tk.LEFT, fill=tk.Y)
    schiebeleiste.config(command=textfenster.yview)
    textfenster.config(yscrollcommand=schiebeleiste.set)
    basisfenster.after(0, text_ausgeben, textfenster, TEXT)
    basisfenster.mainloop()

if __name__ == '__main__':
    main()
Benutzeravatar
noisefloor
User
Beiträge: 3854
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,
Geht das mit stdout oder subprocess und wenn ja WIE ?
Nein, das geht anders.

Das Text-Widget kennt eine Methode Namens "insert", mit der du Text einfügen kannst.
Wie gesagt, die Lösungen die annähernd im WWW beschrieben werden sind sehr oft in Englisch und ich verstehe nur Bahnhof.
Grundsätzlich schlecht, weil quasi die gesamte Doku zu Python und viele andere Supportquellen (z.B. Stack Overflow) auf Englisch sind. Oder anders: wenn du Englisch nicht zumindest lesend so halbwegs verstehst, dann wird's schwierig. Gilt genau so für alle anderen Programmiersprachen.

Gruß, noisefloor

Nachtrag: Sirius3 war schneller...
Max77
User
Beiträge: 19
Registriert: Samstag 30. April 2016, 13:42

Hallo,

erst mal danke für die Antworten.

Aber ich habe meine Frage falsch formuliert. Das mit der insert-Anweisung
kenne ich schon. Mit normalem Text-String auch kein Problem.

Ich meine eigentlich ob ich die Ausgaben die die Python-Shell generiert
in das Text-Widget umleiten kann und wie.
BlackJack

@Max77: Wieso die Python-Shell? Du startest Programme ja nicht aus einer Python-Shell. Und um welche Ausgaben handelt es sich da? Wenn Du in Deinem Programm ``print`` verwenden kannst, dann kannst Du stattdessen ja auch einfach `insert()` verwenden.
Benutzeravatar
noisefloor
User
Beiträge: 3854
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

@Max77: es würde sehr helfen, wenn du mal etwas ausführlicher beschreibst _was_ der Sinn der Übung ist bzw. wozu das ganze gut sein soll. Du willst das ja (wahrscheinlich) nicht aus Spaß an der Freude machen, sondern hast konkrete Absichten.

Gruß, noisefloor
BlackJack

@Max77: Ein paar Anmerkungen zum Quelltext:

Der Quelltext ist syntaktisch nicht korrekt.

Der Sternchen-Import ist keine gute Idee und da sind zu viele Leerzeilen.

Auf Modulebene sollten nur Definitionen von Konstanten, Funktionen, und Klassen stehen. Das Hauptrogramm steht üblicherweise in einer Funktion die `main()` heisst.

Für `Text` mit Scrollbalken gibt es in der Standardbibliothek das Modul `ScrolledText` mit einer gleichnamigen Klasse.

Die Namenschreibweise von `Text_ausgeben()` entspricht nicht dem Style Guide for Python Code.

`after()` wird falsch verwendet. Da wird als zweites Argument eine *Funktion* erwartet, Du übergibst dort aber `None`. Das ist der Rückgabewert von `Text_ausgeben()`. Wenn man eine Verzögerung von 0 wählt, wollte man eher `after_idle()` verwenden. An der Stelle hier macht beides aber keinen Sinn.
Max77
User
Beiträge: 19
Registriert: Samstag 30. April 2016, 13:42

Hallo BlackJack

Ich habe ein Programm geschrieben was mir von den Dateien in einem Verzeichnis und seinen Unterverzeichnissen die MD5-Prüfsumme nimmt.

Die Dateinamen und deren MD5-Prüfsumme wird in einer sqlite3-Datei und in zwei SHELVE-Dateien gespeichert.

Damit will ich später einmal feststellen können ob sich Foto- und Videodateien noch im Urzustand befinden bzw. verändert wurden oder sich durch bitkippen geändert haben.

Soweit funktioniert das Programm auch wie es soll.
ABER – Arbeite mit der Python-IDLE und diese öffnet beim Start immer eine Shell in der ich den Ablauf des Programms verfolgen kann.
Ich finde die IDLE für Python 2.7.1 auch ganz gut. Sie hat mir sehr geholfen das Programm zu Entwickeln.

Nun möchte ich aber für's fertige Programm die Shell-Ausgaben der IDLE in ein ScrolledText-Widget in ECHTZEIT umleiten.
Ich habe also den entsprechenden Programmabschnitt wiederholt und die print-Anweisungen durch textfenster.insert("end", x[0]) ersetzt.

Nun öffnet sich auch das ScrolledText Fenster mit dem Buttons.
Starte ich nun das Programm läuft es erst zu Ende und erst dann erscheint die kommplette Ausgabe im ScrolledText-Fenster. Bis dahin bleibt es leer.

Ich möchte aber das WÄHREND des PROGRAMMLAUFES die insert-Meldungen im ScrolledText-Fenster erscheinen.
Wie kann ich dieses Verhalten bewerkstelligen ?


Code: Alles auswählen

# -*- coding: utf-8 -*-

from Tkinter import *
import sys , os , shelve , hashlib
from tkFileDialog import askdirectory
import unicodedata , sqlite3
from ScrolledText import ScrolledText




basisfenster = Tk()
basisfenster.title("Von den Dateien in einem Verzeichnis und seinen Unterverzeichnissen die Fingerabdrücke nehmen.")
                    

textfenster = ScrolledText(height=35,width=90, font='courier 18', background='white', foreground='blue')
textfenster.pack(side=LEFT , fill=Y)


pruefsumme = StringVar()


  



#import os , shelve , hashlib , unicodedata , sqlite3


class Dateifingerabdruck():

    def __init__(self, python_shell=0):

        self.py_shell = python_shell

    

    def walken(self, pfad_ord, pfad_er):
         
         self.pfad_ordner = pfad_ord
         self.pfad_ergebnis = pfad_er
         

         if self.py_shell == 1:
             
             verbunden_mit_db = sqlite3.connect(os.path.join(self.pfad_ergebnis , 'fingerabdruecke.db'))                                          ###

             positionsanzeiger = verbunden_mit_db.cursor()

             positionsanzeiger.execute("""CREATE TABLE Fingerabdruecke (Dateinamen TEXT , MD5_Hash TEXT , Pfad TEXT)""")


            
             for x in os.walk(self.pfad_ordner):

                       
                 os.chdir(str(x[0]))
                 

                 print "#################################################################################################"
                        

                 print " "

                 print x[0]
                 


                 print " "

                 print x[2]

                 print " "
                       
                 dateiliste = len(x[2])
                 print dateiliste
                        
                 print " "
                 print " "
                        
                        
                 fingerabdruck = hashlib

                 z = 0


#########################################################################################################
#########################################################################################################

                 for i in range(dateiliste):
    
                     try:
                                                                                                            
                         einzeldatei = x[2][z]

                         print einzeldatei

                         print " "


                         einzeldatei_geoeffnet = file(einzeldatei , 'rd')
                         ''' Wenn die GESCHÜTZTE-Datei Pöppel.jpg geöffnet werden
                         soll gibt Python eine IOError-Fehlermeldung aus die durch
                         die exept-Anweisung abgefangen wird bzw. Das Programm
                         bricht an dieser Stelle ab und springt zu
                         "except IOError, io_exception:"
                         Von dort wird das Programm fortgesetzt und zu
                         "try:"
                         zurück gesprungen.'''

                         einzeldatei_geoeffnetDATA = einzeldatei_geoeffnet.read()

                         pruefsumme.set(fingerabdruck.md5(einzeldatei_geoeffnetDATA).hexdigest())

                         einzeldatei_geoeffnet.close()

                         print pruefsumme.get()

                         ########################################################################

                         woerterbuch = shelve.open(os.path.join(self.pfad_ergebnis , 'SHELVE_Dict_MD5'))                                          ###
            
                         woerterbuch[einzeldatei] = pruefsumme.get()

                         woerterbuch.close()

                         ########################################################################

                         woerterbuch = shelve.open(os.path.join(self.pfad_ergebnis , 'SHELVE_Dict_Path'))                                         ###
            
                         woerterbuch[einzeldatei] = x[0]

                         woerterbuch.close()

                         ########################################################################

                         print " "
                         print " "
                         print " "
                         print " "

                         ########################################################################
                                                                                                                                                            
                         werte = (einzeldatei.decode('utf-8') , pruefsumme.get() , x[0].decode('utf-8'))

                         sql = "INSERT INTO Fingerabdruecke VALUES (? , ? , ?)"

                         positionsanzeiger.execute(sql, werte)
            
                         verbunden_mit_db.commit()

                         z = z + 1

                         ########################################################################

#########################################################################################################
#########################################################################################################



#########################################################################################################
#########################################################################################################

                     except IOError, io_exception:
                                                                                                                                              
                         print "Fehler beim Öffnen der Datei", io_exception.filename
                        
                         print " "

                         print "Fingerabdruck konnte NICHT genommen werden !"

                         print " "
                         print " "
                         print " "

                         z = z + 1

                         ########################################################################################

                         woerterbuch = shelve.open(os.path.join(self.pfad_ergebnis , 'SHELVE_Dict_MD5'))                                          ###
            
                         woerterbuch[io_exception.filename] = "KEIN Fingerabdruck vorhanden"

                         woerterbuch.close()

                         ########################################################################################

                         woerterbuch = shelve.open(os.path.join(self.pfad_ergebnis , 'SHELVE_Dict_Path'))                                         ###
            
                         woerterbuch[io_exception.filename] = x[0]

                         woerterbuch.close()

                     ########################################################################################

                         werte = (io_exception.filename.decode('utf-8') , 'KEIN Fingerabdruck vorhanden' , x[0].decode('utf-8'))

                         sql = "INSERT INTO Fingerabdruecke VALUES (? , ? , ?)"

                         positionsanzeiger.execute(sql, werte)
            
                         verbunden_mit_db.commit()


########################################################################################################
########################################################################################################
########################################################################################################
                         
                         

         if self.py_shell == 0:

             verbunden_mit_db = sqlite3.connect(os.path.join(self.pfad_ergebnis , 'fingerabdruecke.db'))                                          ###

             positionsanzeiger = verbunden_mit_db.cursor()

             positionsanzeiger.execute("""CREATE TABLE Fingerabdruecke (Dateinamen TEXT , MD5_Hash TEXT , Pfad TEXT)""")


            
             for x in os.walk(self.pfad_ordner):                                                                                  
                       
                 os.chdir(str(x[0]))


                 
                 textfenster.insert("end", "###################################################################################" )
                        

                 
                 textfenster.insert("end", "\n" )
                 textfenster.insert("end", "\n" )

                 
                 textfenster.insert("end", x[0])


                 
                 textfenster.insert("end", "\n" )
                 textfenster.insert("end", "\n" )

                 
                 textfenster.insert("end", x[2] )

                 
                 textfenster.insert("end", "\n" )
                 textfenster.insert("end", "\n" )
                       

                 dateiliste = len(x[2])

                 
                 textfenster.insert("end",str(dateiliste))
                        

                 
                 
                 textfenster.insert("end", "\n" )
                 textfenster.insert("end", "\n" )
                 textfenster.insert("end", "\n" )
                        
                        
                 fingerabdruck = hashlib

                 z = 0


#########################################################################################################
#########################################################################################################

                 for i in range(dateiliste):
    
                     try:
                                                                                                            
                         einzeldatei = x[2][z]

                         
                         textfenster.insert("end", einzeldatei )

                         
                         textfenster.insert("end", "\n" )


                         einzeldatei_geoeffnet = file(einzeldatei , 'rd')
                         ''' Wenn die GESCHÜTZTE-Datei Pöppel.jpg geöffnet werden
                         soll gibt Python eine IOError-Fehlermeldung aus die durch
                         die exept-Anweisung abgefangen wird bzw. Das Programm
                         bricht an dieser Stelle ab und springt zu
                         "except IOError, io_exception:"
                         Von dort wird das Programm fortgesetzt und zu
                         "try:"
                         zurück gesprungen.'''

                         einzeldatei_geoeffnetDATA = einzeldatei_geoeffnet.read()

                         pruefsumme.set(fingerabdruck.md5(einzeldatei_geoeffnetDATA).hexdigest())

                         einzeldatei_geoeffnet.close()

                         
                         textfenster.insert("end", str(pruefsumme.get()) )

                         ########################################################################

                         woerterbuch = shelve.open(os.path.join(self.pfad_ergebnis , 'SHELVE_Dict_MD5'))                                          ###
            
                         woerterbuch[einzeldatei] = pruefsumme.get()

                         woerterbuch.close()

                         ########################################################################

                         woerterbuch = shelve.open(os.path.join(self.pfad_ergebnis , 'SHELVE_Dict_Path'))                                         ###
            
                         woerterbuch[einzeldatei] = x[0]

                         woerterbuch.close()

                         ########################################################################

                         
                         textfenster.insert("end", "\n" )
                         textfenster.insert("end", "\n" )
                         textfenster.insert("end", "\n" )
                         textfenster.insert("end", "\n" )
                         textfenster.insert("end", "\n" )

                         ########################################################################
                                                                                                                                                            
                         werte = (einzeldatei.decode('utf-8') , pruefsumme.get() , x[0].decode('utf-8'))

                         sql = "INSERT INTO Fingerabdruecke VALUES (? , ? , ?)"

                         positionsanzeiger.execute(sql, werte)
            
                         verbunden_mit_db.commit()

                         z = z + 1

                         ########################################################################

#########################################################################################################
#########################################################################################################



#########################################################################################################
#########################################################################################################

                     except IOError, io_exception:
                                                                                                                                              
                         
                         textfenster.insert("end", "Fehler beim Öffnen der Datei", str(io_exception.filename) )
                        
                         
                         textfenster.insert("end", "\n" )
                         textfenster.insert("end", "\n" )

                         
                         textfenster.insert("end", "Fingerabdruck konnte NICHT genommen werden !" )

                         textfenster.insert("end", "\n" )
                         textfenster.insert("end", "\n" )
                         textfenster.insert("end", "\n" )
                         textfenster.insert("end", "\n" )

                         z = z + 1

                         ########################################################################################

                         woerterbuch = shelve.open(os.path.join(self.pfad_ergebnis , 'SHELVE_Dict_MD5'))                                          ###
            
                         woerterbuch[io_exception.filename] = "KEIN Fingerabdruck vorhanden"

                         woerterbuch.close()

                         ########################################################################################

                         woerterbuch = shelve.open(os.path.join(self.pfad_ergebnis , 'SHELVE_Dict_Path'))                                         ###
            
                         woerterbuch[io_exception.filename] = x[0]

                         woerterbuch.close()

                     ########################################################################################

                         werte = (io_exception.filename.decode('utf-8') , 'KEIN Fingerabdruck vorhanden' , x[0].decode('utf-8'))

                         sql = "INSERT INTO Fingerabdruecke VALUES (? , ? , ?)"

                         positionsanzeiger.execute(sql, werte)
            
                         verbunden_mit_db.commit()


#################################################################################################################
#################################################################################################################
#################################################################################################################


pfadname1 = StringVar()
pfadname2 = StringVar()


pruefsummen = Dateifingerabdruck()


def hashen():
    
    hash_verzeichnis = askdirectory()

    pfadname1.set(os.path.abspath(hash_verzeichnis))


def ausgabe():

    ausgabe_verzeichnis = askdirectory()

    pfadname2.set(os.path.abspath(ausgabe_verzeichnis))

    

def fingerprints():

    pruefsummen.walken(pfadname1.get() , pfadname2.get())

       

             
knopf1 = Button(basisfenster, text='welchen Ordner hashen ?', highlightbackground='white',command=hashen)
knopf1.pack(pady = 10)

knopf2 = Button(basisfenster, text='Wohin die Fingerabdrücke ?', highlightbackground='white',command=ausgabe)
knopf2.pack(pady = 30)

knopf3 = Button(basisfenster, text='UND LOS !', highlightbackground='white',command=fingerprints)
knopf3.pack(pady = 60)




basisfenster.mainloop()
Zuletzt geändert von Anonymous am Samstag 25. Juni 2016, 16:43, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

@Max77: das Programm, wie es hier steht ist unlesbar. Viel zu viele Leerzeilen, und die Zeilen, in denen etwas steht, sind oft viel zu lang. Du versuchst mit Lattenzäunen verschiedene Programmteile abzutrennen, das macht man aber normalerweise durch sinnvoll benannte Funktionen.

*-Importe und mehr als ein Modul pro Importzeile sind schlecht, da sie die Importe unübersichtlich machen und man nicht auf einen Blick sieht, was alles importiert wird.

Auf oberster Ebene sollte kein ausführbarer Code stehen, sondern nur Definitionen. Dann hast Du auch kein Problem damit, dass sich Programm und Definitionen abwechseln und man dem Programmlauf so nur schwer folgen kann.

Die Klasse Dateifingerabdruck ist keine Klasse, weil sie nur aus einer Funktion besteht, die auch noch viel zu lang ist. Du hast zwei Fälle, py_shell=1 und py_shell=0, die sich nur in der Ausgabe unterscheiden, dazu brauchst Du nicht *alles* kopieren, sondern dafür verwendet man eine passende Funktion zur Ausgabe, wie ich sie schon in meinem ersten Beitrag skizziert habe.

Zeile 54: os.walk hat drei Rückgabewerte, die man am besten an drei Variablen mit sinnvollen Namen bindet und nicht an x und dann mit magischen Indizes zugreift.
Zeile 57: os.chdir solltest Du nie benutzen, da es einen globalen Zustand im Programm verändert.
Zeile 75: dateiliste ist keine Liste sondern die Länge einer Liste
Zeile 90: und über diese Liste iteriert man am besten direkt und nicht über einen Index. Ach nein, Du benutzt ja den Index gar nicht sondern zählst nochmal händisch eine weitere Variable z hoch.
Zeile 102: mehrzeilige Strings sind kein Kommentar! Zumal der Kommentar falsch ist, da nie zu try zurückgesprungen wird.
Was ist denn an einzeldatei_geoeffnetDATA wichtig? Dass es sich um eine einzelne Datei handelt? Dass sie geöffnet ist? Oder dass es sich eigentlich um beliebige Daten handelt?
Zeile 121ff: Warum hast Du *zwei* Shelvdateien, die eine zum Speichern von einem Pfad, die andere von einem Hash? Und noch eine weitere Datenbank? Was soll das? Und was passiert, wenn es den selben Dateinamen in unterschiedlichen Verzeichnissen gibt?

Zum Problem: Solange eine Funktion läuft wird das Fenster nicht aktualisiert. Du brauchst also einen Arbeitsthread, der die Dateien durchläuft, eine Queue, die die Ausgabe entgegennimmt und eine per after regelmäßig aufgerufene Funktion im Hauptthread, die die Queue leert und den Inhalt im Fenster anzeigt.
BlackJack

(Upsi, da hatte ich noch das Fenster offen und von dem was ich vorhin schon geschrieben habe, überschneidet sich viel mit dem was Sirius3 in der Zwischenzeit geschrieben hat. Ich bin jetzt zu faul meinen Text noch mal zu überarbeiten. Mehrfachnennung einfach ignorieren (Sind wir hier bei Dalli Dalli? :-D))

@Max77: Okay, das mit der Python-Shell war zum Beispiel etwas was mich bisher immer irritiert hat: Das hat nichts mit IDLE oder eine Python-Shell zu tun. Das sind einfach ``print``-Ausgaben.

Als erstes solltest Du die Programmlogik von der Darstellung sauber trennen. Du hast da ein ``if`` mit zwei grossen Code-Zweigen die im Grunde das gleiche Programm enthalten, einmal mit ``print`` für die Ausgabe und einmal mit `Text.insert()`-Aufrufen für die Ausgabe. Code- und Datenwiederholungen im Quelltext verletzen das DRY-Prinzip („Don't Repeat Yourself“) und machen Programme fehleranfälliger, unnötig länger, und schwerer zu warten.

Eine sinnvolle Trennung wäre Beispielsweise ein Iterator der die vollen Dateinamen liefert. Dann eine Funktion die diesen Iterator entgegennimmt einen Iterator mit dem Dateinamen und der Prüfsumme liefert. Dann eine Funktion die über diese Daten iteriert und die wegspeichert und wieder unverändert als Iterator liefert. Damit hätte man alles ausser der Anzeige einmal als flexible ”zusammensteckbare” Komponenten. Das kann man dann ohne das man Code kopieren und anpassen muss, für verschiedene Anzeigen verwenden. Also ``print`` oder GUI und wenn ja welches GUI-Rahmenwerk sind nun Entscheidungen die vom restlichen bereits vorhandenen Code unabhängig sind.

Die GUI sollte mit einer Klasse umgesetzt werden statt das alles global auf Modulebene, und dann auch noch durch andere Definitionen unterbrochen, stehen zu haben. Auf der anderen Seite sollte diese unsinnige `Dateifingerabdruck`-”Klasse” weg, denn das ist gar keine Klasse, sondern nur eine umständlich geschriebene Funktion.

Wenn man Wahrheitswerte meint, sollte man `True` und `False` schreiben und nicht 1 und 0. Ausser bei den Bedingungen, da sollte man das dann gar nicht mehr schreiben, denn ein expliziter Vergleich eines `bool` mit einem literalen `True` oder `False` ergibt als Ergebnis nur wieder einen `bool`-Wert. Entweder den, den man vor dem Vergleich sowieso schon hatte, oder dessen Negierung. Also kann man auch gleich den Wert verwenden, oder dessen Negierung mit ``not``.

`positionsanzeiger` ist für `cursor` zwar theoretisch die richtige Übersetzung, nur sind DB-API 2.0 `Cursor`-Objekte das nicht wirklich. Man fragt einen Positionszeiger zum Beispiel nicht danach eine Tabelle anzulegen, denn das hat absolut nichts mit der Position innerhalb einer Ergebnismenge zu tun.

`x` ist kein guter Name für ein Tupel aus Pfad, Verzeichnisnamen, und Dateinamen.

`os.chdir()` verändert prozessglobalen Zustand und ist ganz und gar keine gute Idee. Arbeite entsprechenden Pfaden statt diesen Zustand zu ändern. Der `str()`-Aufruf ist an der Stelle zudem entweder überflüssig, oder gar ein Fehler, wenn nämlich als `pfad_ord` (schlechter Name) ein Unicode-Objekt übergeben wurde. Dann kann das `str()` an der Stelle zu einer Ausnahme führen wenn man an einen Dateinamen gerät der nicht nur ASCII-Zeichen enthält.

Für jedes Verzeichnis ``fingerabdruck = hashlib`` auszuführen ist sinnfrei. Diese Umbenennung hätte man einmal beim importieren machen können. Wenn überhaupt. Die Bezeichner würde ich eher englisch wählen.

`z` ist kein guter Name und das ``for i in range(dateiliste)`` ist in Python ein „anti pattern“. Man kann in Python *direkt* über die Elemente von Sequenzdatentypen wie Listen iterieren, ohne den Umweg über einen Laufindex. Wobei das ab da extrem verwirrend wird weil Du manuell zusätzlich zu dem `i` noch ein `z` hochzählst, und das dann verwendest um mit ``x[2][z]`` auf einzelne Dateinamen zuzugreifen. Und das wo `i` doch immer den gleichen Wert hat wie `z` und ``x[2]`` wie man am `range()` sieht bereits an den Namen `dateiliste` gebunden ist. WTF‽

Mehrzeilige Zeichenkettenliterale sind keine Kommentare. Der Inhalt von dem ”Kommentar” ist zudem nicht ganz korrekt, denn von dem ``except``-Block aus wird nicht zum ``try`` zurück gesprungen. *Hinter* dem ``try``-Block befindet sich das Schleifenende und dort wird mit dem Anfang der Schleife fortgefahren. und falls die nicht am Ende ist, wird der Schleifenkörper erneut ausgeführt und man gelangt so wieder in dem ``try``-Block.

Das Vorgehen die komplette Datei in den Speicher zu lesen wird bei heutigen Rechnern mit CD-Images vielleicht noch funktionieren, aber spätestens bei grossen Videos oder DVD-Images wird's sicher auch heute noch bei dem ein oder anderen Desktoprechner eng. Bei kleinen Maschinen, wie beispielsweise einem Raspberri Pi, ist die Luft da deutlich eher raus und das Programm bricht mit einem `MemoryError` ab.

Die Daten in den Shelve-Dateien funktionieren nicht wenn es in mehreren Verzeichnissen Dateien mit dem gleichen Namen gibt. Da muss der gesamte Pfad als Schlüssel verwendet werden. Dann braucht man auch nur *ein* Shelve statt zwei parallel zu führen, mit den Gefahren die das bezüglich der Datenintegrität mit sich bringt.

Hier wiederholt sich auch wieder Code, denn im ``try`` und im ``except`` unterscheidet sich das ganze schreiben in die Datenbanken nur durch *einen* Wert. Dieser Wert sollte im ``try`` und im ``except`` bestimmt werden, und dann gehört das schreiben der Daten *einmal* hinter dieses Kosntrukt.

Nummern an Namen zu hängen ist ein „code smell“. Da will man entweder bessere Namen verwenden, oder eine Datenstruktur. Meistens eine Liste. Im Fall von `pfadname1` und `pfadname2` möchte man aber sinnvollere Namen verwenden, die beschreiben was für eine Bedeutung der jeweilige Pfadname hat. Das Du hier `StringVar` verwendest, hat wahrscheinlich auch hauptsächlich den Grund das das nicht ordentlich objektorientiert gelöst ist und das deshalb über diese globalen Variablen gehen muss.

Zum Problem hat Sirius3 ja auch schon was gesagt.
Max77
User
Beiträge: 19
Registriert: Samstag 30. April 2016, 13:42

Au weia !!! Da habe ich ja einen ganz schönen Mist zusammengeklöppelt. Note: 6 – setzen.

Erst mal dank an Sirius3 und BlackJack das ihr euch die Mühe gemacht habt meinen Schrott-Code zu Begutachten.
Wie habt ihr beiden es bloß geschafft diese Sprache zu Erlernen ? Aus Büchern ? Oder IT-Studium ? Ein hoher IQ ?

Ich hatte mir ja schon vor Jahren das Buch: „Objektorientierte Programmierung mit Python“ von Michael Weigend gekauft.
Der Anfang des Buches war auch sehr verständlich geschrieben.
Als es aber in dem Buch mit der OOP los ging habe ich immer weniger verstanden. Ich kann einfach nicht Objektorientiert denken. Die Beispiele die dort gebracht wurden vermochte ich von der Logik her nicht Nachzuvollziehen.

So ähnlich erging es mir mit diversen anderen Fachbüchern zum
gleichen Thema. Erst einfach dann immer Unverständlicher.

Dann habe Ich mir diverse deutschsprachige Tutorials im Internet angesehen aber bis jetzt habe ich keine Anleitung gefunden die mir diese verfluchte Objektorientierung verständlich erklären bzw. beibringen konnte.
Da wird mit Fachausdrücken nur um sich geschmissen ohne dabei an den Anfänger zu denken der ja mit diesen Bezeichnungen überhaupt noch nicht vertraut ist. Zum Beispiel Namesräume. Ich verstehe einfach nicht was Namensräume sind. Was ist eine Quere ? Was ein Iterator ? Ereignismenge ? prozessglobalen Zustand ? Warum ist alles so umständlich benannt ?

Und wenn ich mir per help() auf Shell-Ebene die Modul und Klassenbeschreibungen ansehe verstehe ich noch weniger.
Alles sehr verwirrend aufgelistet.

Und englischsprachige Tutorials verstehe ich gar nicht. Ich habe leider keine Begabung für Fremdsprachen.

Python ist eine leicht zu lernende Sprache ? Für mich mit Nichten.
Mein Grips reicht dafür einfach nicht aus. Das ist das Resümee das ich aus meinen Programmierversuchen ziehe.

Nach Jahren des Studierens von Beispielen und Tutorials habe ich endlich verstanden das ich von OOP aber auch rein gar NICHTS verstanden habe.

ICH GEBE AUF !!!

:( :( :(
BlackJack

@Max77: Vor Python hatte ich schon Kontakt mit vielen anderen Programmiersprachen. Solange eine Sprache nicht komplett anders tickt, als die die man davor gelernt hat, fällt das dann schon mal leichter. Man muss dann nur die ”Differenz” lernen, also einiges aus anderen Sprachen ”verlernen” und was neu oder anders ist dazu lernen. Zum ”verlernen” gehörte bei Python zum Beispiel das Indexzugriffe in Schleifen ”unpythonisch” sind wenn man stattdessen direkt über die Objekte iterieren kann.

Bücher haben bei mir beim lernen von Python noch eine Rolle gespielt, es wäre aber auch ohne gegangen, denn Online war und ist eine Menge Stoff vorhanden. Allerdings das allermeiste in Englisch. Um diese Sprache kommt man beim Programmieren nicht herum.

IT-Studium hat geholfen — hauptsächlich weil ich dort mit Java gequält wurde und deshalb motiviert war was schöneres zu lernen, und dankbar war, dass Python deutlich schöner ist. :-)

Mit Java habe ich eine Spielart von OOP gelernt — diese klassenfixierte, statisch typisierte. Davor kannte ich OOP von Borland Pascal aus der Schule, und da habe ich es nur so halb verstanden gehabt. Danach habe ich mich noch ein bisschen mit Smalltalk beschäftigt, das ist OOP wie's mal erfunden wurde, und mit Io, das ist OOP ohne Klassen.

Namensräume haben nichts mit OOP zu tun, das ist ein orthogonales Thema. Man kann Namensräume auch ohne OOP haben und verwenden. Bei klassischer prozeduraler Programmierung mit Pascal sind Units zum Beispiel Namensräume. Auch ohne eigene Klassen zu definieren, nutzt man in Python schon Module als Namensräume. Klassen sind welche. Eigentlich jedes Objekt, und da in Python jeder Wert ein Objekt ist, ist in Python im Grunde auch jeder Wert ein Namensraum. Man kann allerdings nicht auf jedem Objekt Namen a.k.a. Attribute definieren. Es gibt welche die erlauben das nicht.

Namensräume sind ”Räume” in denen man Namen definieren kann. Eben in einem Modul. Oder in einer Klasse. Und per Zuweisung eines Attributs auf (fast) jedem Objekt.

Was eine „Quere“ ist weiss ich auch nicht, aber eine Queue ist eine Datenstruktur mit bestimmten Eigenschaften. Python hat sowas schon in der Standardbibliothek als `collections.deque` und `Queue.Queue`. Ähnlich wie eine Liste, nur das man da effizient Werte am einen Ende hinzufügen und am anderen entfernen kann. Und die beiden Implementierungen sind threadsicher.

Ein Iterator ist ein Wert mit bestimmten Eigenschaften. Man kann sich mit der `next()`-Funktion ”den nächsten Wert holen” und bekommt entweder diesen Wert oder es wird eine `StopIteration`-Ausnahme ausgelöst. Was ”der nächste Wert” ist, hängt davon ab was das für ein Iterator ist. Dateiobjekte sind beispielsweise Iteratoren und da ist der nächste Wert die nächste Zeile aus der Datei. Wenn man sich von einer Liste mit `iter()` einen Iterator geben lässt, dann liefert der nach und nach die Werte aus der Liste. Iteratoren sind in Python sehr wichtig, denn die kommen in jeder ``for``-Schleife vor. Nach dem ``in`` muss ein Ausdruck stehen der zu einem iterierbaren Objekt ausgewertet wird, also ein Objekt von dem man mit der `iter()`-Funktion einen Iterator bekommt.

Ereignismenge? Ich habe eine Ergebnismenge erwähnt. Und da habe ich jetzt ein ganz klein bisschen ein Problem das Problem zu sehen. Wenn man eine Datenbankabfrage durchführt, bekommt man eine Ergebnismenge. Der Begriff Menge wird hier zugegebenermassen etwas gedehnt, weil eine Menge ungeordnet ist und damit ein Positionsanzeiger keinen Sinn macht, aber so streng sieht man das in der praktischen Anwendung nicht immer. :-)

Prozessglobaler Zustand ist ein Zustand der für den gesamten Prozess gilt, also für alle Teile des Programms. Und wenn Du in einem Teil des Programms das aktuelle Arbeitsverzeichnis änderst, kann es passieren, dass andere Teile des Programms etwas mit Dateien machen und davon ausgehen das sich das Arbeitsverzeichnis *nicht* geändert hat, und dann gibt es Fehler. Globale Zustände sollte man so gut es geht vermeiden. Schon in Modulen, und erst recht für den gesamten Prozess. Das macht Programme undurchsichtig, fehleranfällig, und schwer zu warten.

Es ist eben gerade nicht alles umständlich benannt. Wenn es die Fachbegriffe nicht gäbe, dann müsste man ja jedes mal wenn man eine Queue meint, ausführlich beschreiben was für einen Wert mit welchen Eigenschaften man meint. Und jeder beschreibt das dann ein bisschen anders und jeder versteht das dann ein bisschen anders. Der Begriff Queue ist ziemlich klar definiert, da gibt es relativ wenig Spielraum. Das ist ein abstrakter Datentyp den es in vielen Programmiersprachen implementiert gibt. Bei Iterator ist es so ähnlich, nur das es dort deutlich mehr Spielraum bei der konkreten Umsetzung gibt.

Wenn Du tatsächlich keine Begabung für Fremdsprachen hast, dann liegt vielleicht da das Problem. Programmier*sprachen* sind halt auch Sprachen. Und von keinem von uns die Muttersprachen, also sind es Fremdsprachen. Und Dokumentation ist im Überfluss vorhanden, allerdings überwiegend in Englisch.

Das Python grundsätzlich leicht zu lernen ist wage ich zu bezweifeln. Es ist leichter als bestimmte andere Sprachen, weil es eine recht übersichtliche und lesbare Syntax hat, weil man in der interaktiven Shell leicht experimentieren kann, weil es eine umfangreiche Standardbibliothek gibt, und weil sich die Laufzeitumgebung um die Speicherverwaltung kümmert und hilfreichere Ausgaben liefert als einen kommentarlosen Programmabsturz wenn man Fehler macht.

Die Materie an sich ist halt auch recht komplex. Also Kodierungen und Texte, Betriebssystemkram wie Prozesse/Dateioperationen, GUIs, nebenläufige Programmierung, relationale Datenbanken — das sind alles für sich genommen schon recht umfangreiche Themen. Da braucht man Zeit.

Wenn man das Programm anschaut, fehlt Dir auch noch ein Schritt vor OOP: Funktionen.Wenn man seinen Code nicht sinnvoll auf Funktionen einteilt, und globale Variablen verwendet, dann ist man mindestens zwei Schritte von OOP entfernt. Denn bei OOP werden zusammengehörende Funktionen und Daten zu Objekten zusammengefasst.
Sirius3
User
Beiträge: 17741
Registriert: Sonntag 21. Oktober 2012, 17:20

Um Objektorientierung zu verstehen, habe ich auch mehrere Jahre gebraucht. So etwas aus Büchern zu lernen halte ich für schwierig (wahrscheinlich, weil ich noch nie eine Programmiersprache gelernt habe).
Man muß einfach Programme schreiben, wo es einem nützlich vorkommt, Klassen zu nehmen (oder Java lernen, da stellt sich die Frage nach der Nützlichkeit erst gar nicht).

Daher das ganze noch ohne Klassen, wobei man sieht, dass dieses Übergeben von Parametern langsam Züge annimmt, wo es unübersichtlich wird.

Code: Alles auswählen

# -*- coding: utf-8 -*-
import os
import hashlib
import sqlite3
import Tkinter as tk
from threading import Thread
from Queue import Queue, Empty
from tkFileDialog import askdirectory
from ScrolledText import ScrolledText
 
def calculate_hashes(path, outputpath, writeline):
    database = sqlite3.connect(os.path.join(outputpath, 'fingerabdruecke.db'))
    cursor = database.cursor()
    cursor.execute("""CREATE TABLE Fingerabdruecke (Dateinamen TEXT , MD5_Hash TEXT , Pfad TEXT)""")
 
    for current_path, _, files in os.walk(path):
        writeline("############################")
        writeline("Pfad: %s" % current_path)
        writeline("Anzahl Dateien: %s" % len(files))
        for filename in files:
            try:
                writeline(filename)
                md5 = hashlib.md5()
                with open(os.path.join(current_path, filename), 'rb') as data:
                    while True:
                        bytes = data.read(65536)
                        if not bytes:
                            break
                        md5.update(bytes)
                hash = md5.hexdigest()
                writeline(hash)
            except IOError, io_exception:
                writeline("Fehler beim Öffnen der Datei %s" % io_exception.filename)
                hash = 'KEIN Fingerabdruck vorhanden'
            cursor.execute("INSERT INTO Fingerabdruecke VALUES (? , ? , ?)",
                (filename, hash, current_path))
 
def askpath(pfadname):
    pfadname.set(os.path.abspath(askdirectory()))

def update(textfenster, queue):
    try:
        while True:
            textfenster.insert("end", queue.get_nowait()+'\n')
    except Empty:
        textfenster.after(100, update, textfenster, queue)
            
def start_hashing(textfenster, path_to_hash, outputpath):
    queue = Queue()
    textfenster.after(100, update, textfenster, queue)
    Thread(target=calculate_hashes, args=(path_to_hash, outputpath, queue.put)).start()

def main():
    basisfenster = tk.Tk()
    basisfenster.title("Von den Dateien in einem Verzeichnis und seinen Unterverzeichnissen die Fingerabdrücke nehmen.")
    textfenster = ScrolledText(height=35,width=90, font='courier 18', background='white', foreground='blue')
    textfenster.pack(side=tk.LEFT , fill=tk.Y)
 
    path_to_hash = tk.StringVar()
    outputpath = tk.StringVar()
             
    knopf1 = tk.Button(basisfenster, text='Welchen Ordner hashen?', highlightbackground='white',
        command=lambda: askpath(path_to_hash))
    knopf1.pack(pady = 10)
    tk.Label(textvariable=path_to_hash).pack()
    
    knopf2 = tk.Button(basisfenster, text='Wohin die Fingerabdrücke?', highlightbackground='white',
        command=lambda: askpath(outputpath))
    knopf2.pack(pady = 30)
    tk.Label(textvariable=outputpath).pack()
    
    knopf3 = tk.Button(basisfenster, text='UND LOS !', highlightbackground='white',
        command=lambda: start_hashing(textfenster, path_to_hash.get(), outputpath.get()))
    knopf3.pack(pady = 60)
    
    basisfenster.mainloop()

if __name__ == '__main__':
    main()
BlackJack

Mal ein Ansatz wie man den Teil mit der Geschäftslogik funktional umsetzen kann und ohne feste Bindung zu einer bestimmten Ausgabe. Es steckt alles in kleinen, übersichtlichen Funktionen die jeweils eine Teilaufgabe lösen und die Ausgaben werden nicht mit einer festen Funktion oder Methode erledigt, sondern über eine Funktion die als Argument übergeben wird. Da kann man dann wie im Beispiel `print` übergeben, aber man könnte auch die `put()`-Methode von einem `Queue`-Exemplar übergeben. Oder eine Funktion die die Ausgaben in eine Datei schreibt. Oder an einen Server sendet, oder…

Code: Alles auswählen

#!/usr/bin/env python
# coding: utf8
from __future__ import absolute_import, division, print_function
import hashlib
import os
import shelve
import sqlite3
from contextlib import closing
from functools import partial
from itertools import imap

SQLITE_DB_FILENAME = 'fingerprints.db'
TABLE_NAME = 'fingerprint'
CREATE_TABLE_SQL = (
    'CREATE TABLE {0} (filename TEXT, md5_hash TEXT, path TEXT)'.format(
        TABLE_NAME
    )
)
INSERT_RECORD_SQL = 'INSERT INTO {0} VALUES (?, ?, ?)'.format(TABLE_NAME)

SHELVE_FILENAME = 'fingerprints.shelve'


def iter_paths(base_path, output_callback):
    for root, _dirnames, filenames in os.walk(base_path):
        output_callback('{0} - {1} file(s).'.format(root, len(filenames)))
        for filename in filenames:
            output_callback('  ' + filename)
            yield os.path.join(root, filename)


def hash_file(filename, block_size=64 * 1024):
    try:
        with open(filename, 'rb') as in_file:
            md5 = hashlib.md5()
            for block in iter(partial(in_file.read, block_size), b''):
                md5.update(block)
    except OSError:
        return (filename, None)
    else:
        return (filename, md5.hexdigest())


def format_record(output_callback, record):
    full_path, checksum = record
    if checksum is None:
        output_callback(
            'Error: Could not take fingerprint from {0}!'.format(
                os.path.basename(full_path)
            )
        )
    else:
        output_callback(checksum)


def save_to_db(connection, record):
    full_path, checksum = record
    path, filename = os.path.split(full_path)
    cursor = connection.cursor()
    cursor.execute(INSERT_RECORD_SQL, (filename, checksum, path))
    connection.commit()


def save_to_shelve(filename, record):
    full_path, checksum = record
    with closing(shelve.open(filename)) as path2checksum:
        path2checksum[full_path] = checksum


def apply_many(functions, item):
    for function in functions:
        function(item)


def process_files(
    result_path, sqlite_db_filename, shelve_filename, base_path, output_callback
):
    with closing(
        sqlite3.connect(os.path.join(result_path, sqlite_db_filename))
    ) as connection:
        cursor = connection.cursor()
        cursor.execute(CREATE_TABLE_SQL)
        connection.commit()
        for record in imap(hash_file, iter_paths(base_path, output_callback)):
            apply_many(
                [
                    partial(format_record, output_callback),
                    partial(save_to_db, connection),
                    partial(
                        save_to_shelve,
                        os.path.join(result_path, shelve_filename)
                    )
                ],
                record
            )


def main():
    process_files(
        './tmp', SQLITE_DB_FILENAME, SHELVE_FILENAME, './tmp/forum', print
    )


if __name__ == '__main__':
    main()
GUI habe ich hier jetzt erst einmal weg gelassen, denn IMHO sollte man nicht mit GUIs anfangen solange man bei Grundlagen wie Funktionen, und vor GUIs dann auch Klassen, nicht sattelfest genug ist. Bei Dir würde wegen der länger laufenden Aktion die fortlaufend Daten in der GUI anzeigen soll, auch noch nebenläufige Programmierung dazu kommen. Was für sich genommen ein kompliziertes Thema ist, auch ohne GUI. Wenn man versucht Funktionen, OOP, ereignisbasierte Programmierung mit GUIs, und nebenläufige Programmierung *auf einmal* zu lernen, dann ist Frustration eigentlich schon vorprogrammiert. Das ist wirklich viel auf einmal.
Max77
User
Beiträge: 19
Registriert: Samstag 30. April 2016, 13:42

Sooo - Nachdem mein Frust etwas verraucht ist bin ich wieder zurück.
Erst mal Danke für die letzten Codebeispiele. Ich habe aber leider nichts davon verstanden und werde
erst mal von Klassen,komplizierten Funktionen und GUI die Finger lassen.

Zurück zu den Basics :mrgreen:
Max77
User
Beiträge: 19
Registriert: Samstag 30. April 2016, 13:42

Hallo Sirius3,

habe mir noch mal deinen Code angesehen in der Hoffnung zumindest ein wenig (sehr wenig) davon zu Verstehen.

z.B. in 16. steht:

for current_path, _, files in os.walk(path):

Was hat denn dieser vereinsamte Unterstrich zu Bedeuten ?
soll "_" das schon eine Variable sein ?
BlackJack

@Max77: Jup, der Unterstrich ist ein gültiger Name. Wird konventionell für Werte verwendet wo man aus syntaktischen Gründen einen Namen schreiben muss, man aber an dem Wert kein Interesse hat und ihn deshalb nicht verwendet.
Max77
User
Beiträge: 19
Registriert: Samstag 30. April 2016, 13:42

@BlackJack: Aus syntaktischen Gründen ??? Wenn dieser Unterstrich nicht verwendet wird und auch dessen Wert nicht interessiert warum schreibt man ihn dann ?
Kann man den nicht weg lassen ?

Was bedeutet aus syntaktischen Gründen ? Wieso will der Python-Interpreter den Unterstrich haben ?

Kannst du ein einfaches Beispiel geben woraus dieser Sinn ersichtlich wird ?


[ HIELFE - DIESE PROFIS MACHEN SO KOMISCHE SACHEN :) ]


PS: Was hälst du von meinem Video ? Gibt es den Sachverhalt richtig wieder ?

https://click.email.vimeo.com/?qs=9d9b9 ... a157328447
BlackJack

@Max77: Wenn man rechts von der Zuweisung ein Tupel mit drei Werten hat, dann müssen links davon auch drei Namen stehen. Auch wenn einen nicht alle drei Werte interessieren. Wenn da nur zwei Namen stünden, wie sollte dann die Zuweisung von drei Werten funktionieren?

Code: Alles auswählen

In [1]: xs = (23, 'uninteressant', 42)

In [2]: a, _, b = xs

In [3]: a
Out[3]: 23

In [4]: b
Out[4]: 42
Python will an der Stelle nicht den Unterstrich haben, aber einen Namen, denn da wird ein Wert zugewiesen und dafür braucht man einen Namen. Man könnte jetzt anstelle des Unterstrichs auch einen anderen Namen nehmen, beispielsweise:

Code: Alles auswählen

In [6]: a, dummy, b = xs

In [7]: a
Out[7]: 23

In [8]: dummy
Out[8]: 'uninteressant'

In [9]: b
Out[9]: 42
`dummy` wäre aber ein Name den man vielleicht auch sinnvoll für einen Wert verwenden könnte der einen im weiteren Programmverlauf interessiert. Oder auch nicht, aber ein Leser könnte das trotzdem erwarten und sich wundern warum der Name an einen Wert gebunden wird, dann aber nicht verwendet wird. Und sich fragen ob das ein Fehler im Programm ist, oder ob es nicht nicht fertig ist, und da noch irgend etwas mit dem Wert gemacht werden sollte. `_` ist ein Name der keine Bedeutung vermittelt, und er ist sehr ”unauffällig”, und ein '_' wird in der Informatik auch manchmal als Zeichen für ein „blank“ verwendet wo man dieses ”Leerzeichen” von anderen Leerzeichen im Text unterscheiden können muss. Und es gibt andere Programmiersprachen wo das festerer Bestandteil der Syntax ist, statt einfach nur ein Name wie jeder andere, und wo es aber genau in dieser Bedeutung gebraucht wird: hier steht ein Wert, der interessiert aber nicht. Beispiel dafür wäre die „pattern matching“-Syntax bei Haskell.
Max77
User
Beiträge: 19
Registriert: Samstag 30. April 2016, 13:42

Das mit dem Tupelauspacken und dem Sinn des Unterstrichs habe ich nun verstanden.


Bei Zeile 16.

for current_path, _, files in os.walk(path):

packst du auch eine Tupel mit drei Elementen aus.

current_path , _ , files = Tupel

WO aber wird im Code die Tupel eingepackt ? Das muß doch VORHER zwischen Zeile 1. und 15.
geschehen. Denn wer Auspacken will muß ja auch vorher Eingepackt haben.
Antworten