Lister - Programmidee

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.
BlackJack

@xeike: Man muss das ja nicht in einer so aufwändigen Klasse machen. Und wieder einmal kommt die `iter()`-Funktion mit zwei Argumenten zum Einsatz :-):

Code: Alles auswählen

# ...
    for block in iter(partial(in_file.read, blocksize), ''):
        sha.update(block)
# ...
Mit `partial()` aus dem `functools`-Modul.

Ich würde auch nicht sagen das Java voll von sauberen Lösungen ist. Das was die so schrecklich macht ist nicht das sie sauber sind, sondern das sie so oft komplex bis „over engineered” sind.
xeike
User
Beiträge: 83
Registriert: Donnerstag 28. Februar 2013, 09:58

BlackJack hat geschrieben:@xeike: Man muss das ja nicht in einer so aufwändigen Klasse machen. Und wieder einmal kommt die `iter()`-Funktion mit zwei Argumenten zum Einsatz :-)
:lol:
Das was die so schrecklich macht ist nicht das sie sauber sind, sondern das sie so oft komplex bis „over engineered” sind.
Ja, over-engineered :idea: war das Wort, das ich gesucht habe.
nezzcarth
User
Beiträge: 1651
Registriert: Samstag 16. April 2011, 12:47

Gary123456 hat geschrieben:Ich habe mein Bestes gegeben. Was der "Chef" dazu sagen würde, wäre mir egal, da ich in Python noch übe. Ich finde diese Aussage nicht fair. Dennoch versuche ich den Code zu verbessern.
Na ja, im Prinzip ist das das, was ich auch schon mal versucht hatte dir nahe zu legen: deine Beiträge (sowohl die, in denen es um deinen eigenen Code geht, als auch die, in denen du anderen Ratschläge gibst), erwecken den Eindruck, als hättest du einen Kenntnisstand, der sich in deinen Code-Beispielen leider so nicht widerspiegelt; und noch immer beherzigst du beispielsweise die Vermeidung von Code auf Modulebene nicht konsequent. Da musst du dich dann halt auch nicht wundern, wenn solche Antworten kommen :)

Ich denke, jeder hat Verständnis für Anfänger, aber etwas Zurückhaltung und Bescheidenheit wären vielleicht ganz nützlich ;) - insbesondere auch für dich selbst.
Gary123456
User
Beiträge: 318
Registriert: Dienstag 26. Februar 2013, 18:39

Darin wird der Inhalt des Arbeitsspeichers ausgelagert wenn du deinen Computer in den Standby modus versetzt.
Jap, das ist mir klar (http://www.winfaq.de/faq_html/Content/t ... ip1390.htm). Dazu hat sich ein anderen Programmierprofi gemeldet und mir da was erklärt.
Dann schau dir bspw. mal shasum an, du brichst eine Endlosschleife via break ab statt über die Kopfbedingung zu gehen, warum gibts die wohl?
Deine Einrückung beim return ist auch so ein Ding.
Ist die Sache nun geklärt?

Ich weiß jetzt nicht, wo ich stehe. Was auszusetzen am Code?
erwecken den Eindruck, als hättest du einen Kenntnisstand, der sich in deinen Code-Beispielen leider so nicht widerspiegelt; und noch immer beherzigst du beispielsweise die Vermeidung von Code auf Modulebene nicht konsequent.
Ich schaffe oft einen Code, der funktioniert, jedoch scheint dieser oft nicht euren Ansprüchen genug zu sein, da der entweder keine vernünftigen Datenstrukuren besitzt oder vom Aufbau her falsch ist. Ich habe in der Theorie viel gemacht. Da aber das praktisch genau so wichtig ist, will ich es mit diesem Programm üben. Und ich persönlich finde, dass ich mich im Gegensatz zu den alten Threads weiterentwickelt habe. Wer anderer Meinung ist, kann das gerne hier sagen. Dann der zweite Punkt, ihr alle sagt, dass ich Code auf Modulebene schreibe. Dann frage ich mich, was das bedeuten soll.

-Gary
xeike
User
Beiträge: 83
Registriert: Donnerstag 28. Februar 2013, 09:58

Gary123456 hat geschrieben:Dann der zweite Punkt, ihr alle sagt, dass ich Code auf Modulebene schreibe. Dann frage ich mich, was das bedeuten soll.
Code auf Modulebene heißt, dass du deinen Code nicht in Funktionen packst und ihn in einer Funktion an passender Stelle ausführst.

Ungefähr so soll es dann aussehen:

Code: Alles auswählen

# test.py

class TolleKlasse:
    pass

def meine_neue_funktion(parameterliste):
    pass

def main():
    meine_neue_funktion("blah")
    noch(was)
    viel(mehr)

if __name__ == "__main__":
    # hier kommt der Code rein
    main()

Im Gegensatz zu vielen Aufrufen auf der Ebene des Moduls. Denke mal daran, was passiert, wenn jemand dein Skript per "import" importiert...

:wink:

Xe
Gary123456
User
Beiträge: 318
Registriert: Dienstag 26. Februar 2013, 18:39

Bedeutet, dass ich das alles per main() steuern soll? Und so bessere Kontrolle über Funktionen habe? Verstehe es immer noch nicht ganz ...
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

"Steuern" ist ein wenig übertrieben. Im Prinzip solltest du deine Programme so schreiben, dass der gesamte Code in Funktionen und Klassen liegt (abgesehen von den Importen). Der Einstiegspunkt in dein Programm liegt in der main-Funktion. Dort kannst du im Prinzip alles machen was du willst.

Mit dem Konstrukt

Code: Alles auswählen

if __name__ == "__main__":
   main()
wird sichergestellt, dass main nur dann ausgeführt wird, wenn das Programm direkt gestartet wird. Wenn du das Modul importierst, dann wird nichts gemacht. Damit ermöglichst du die Wiederverwendbarkeit deines Codes. Teste das einfach mal, indem du die folgenden beiden Module anlegst und importiertst und direkt startest.

Code: Alles auswählen

if __name__ = "__main__":
    print "Test"

Code: Alles auswählen

print "Test"
Importierst du das erste Modul, so wird keine Ausgabe gemacht. Startest du das erste Modul, dann bekommst du "Test" zu sehen. Beim zweiten Modul wird in jedem Fall "Test" ausgegeben.
Das Leben ist wie ein Tennisball.
Gary123456
User
Beiträge: 318
Registriert: Dienstag 26. Februar 2013, 18:39

Ich überlege mir gerade, ob bei diesem Code eine Klasse sinnvoll ist. Ich meld mich morgen :)
Gary123456
User
Beiträge: 318
Registriert: Dienstag 26. Februar 2013, 18:39

Ich habe rumgetüftelt und kann mir bei einem Code das Verhalten einfach nicht erklären:

komisches Verhalten:

Code: Alles auswählen

import os
import sha


class Lister(object):
    def __init__(self, verzeichnisse, geschuetzt):
        self.verzeichnisse = verzeichnisse
        self.geschuetzt = geschuetzt

    def listen(self):
        for self.path in self.verzeichnisse:
            for self.entry in os.listdir(self.path):
                return os.path.join(self.path, self.entry)


    def shasum(self, filepath, blocksize = 1024 * 1024): 
        self.h = sha.new()
        with open(filepath, "rb") as f:
            try:
                while True:
                    self.part = f.read(blocksize)
                    if not part:
                        break
                    h.update(part)
            finally:
                f.close()   
                return h.hexdigest()

def main():
    verzeichnisse = ["C:\\"]
    geschuetzt = []
    Klasse = Lister(verzeichnisse, geschuetzt)
    print Klasse.listen()
    #COde kommt noch!


if __name__ == "__main__":
    main()
        
Ausgabe:

Code: Alles auswählen

C:\$Recycle.Bin
richtiger Code:

Code: Alles auswählen

import os
import sha


class Lister(object):
    def __init__(self, verzeichnisse, geschuetzt):
        self.verzeichnisse = verzeichnisse
        self.geschuetzt = geschuetzt

    def listen(self):
        for self.path in self.verzeichnisse:
            for self.entry in os.listdir(self.path):
                print os.path.join(self.path, self.entry)


    def shasum(self, filepath, blocksize = 1024 * 1024): 
        self.h = sha.new()
        with open(filepath, "rb") as f:
            try:
                while True:
                    self.part = f.read(blocksize)
                    if not part:
                        break
                    h.update(part)
            finally:
                f.close()   
                return h.hexdigest()

def main():
    verzeichnisse = ["C:\\"]
    geschuetzt = []
    Klasse = Lister(verzeichnisse, geschuetzt)
    Klasse.listen()
    #COde kommt noch!


if __name__ == "__main__":
    main()
Ausgabe:

Code: Alles auswählen

C:\$Recycle.Bin
C:\AMD
C:\Documents and Settings
C:\Dokumente und Einstellungen
C:\hiberfil.sys
C:\MSOCache
C:\pagefile.sys
C:\PerfLogs
C:\Program Files
C:\Program Files (x86)
C:\ProgramData
C:\Programme
C:\Put a directory on PYTHONPATH here
C:\Python25
C:\Python27
C:\Recovery
C:\System Volume Information
C:\test.exe
C:\Users
C:\VS_EXPBSLN_x64_deu.CAB
C:\VS_EXPBSLN_x64_deu.MSI
C:\Windows
C:\XProfanX2
C:\zoek-results07.04.2013-2116.log
>>> 
Return gibt Werte zurück. Das heist Du kannst mit der Ausgabe was machen. Aber kann dieses return nur einen Wert zurück liefern, oder wie? *verwirrt*
nomnom
User
Beiträge: 487
Registriert: Mittwoch 19. Mai 2010, 16:25

Gary123456 hat geschrieben:Return gibt Werte zurück. Das heist Du kannst mit der Ausgabe was machen. Aber kann dieses return nur einen Wert zurück liefern, oder wie? *verwirrt*
Du kannst nur ein Objekt zurückgeben. Dieses Objekt kann allerdings auch eine Liste sein, ein Klassenexemplar, sogar Klassen oder Funktionen. Lister.listen müsste also die Einträge in einer Liste oder einer ähnlichen Datenstruktur sammeln und diese dann zurückgeben oder allerdings du machst daraus einen Generator, dafür einfach return durch yield ersetzen.

Edit: Warum machst du path zu einem Attribut? Das ist doch unsinnig, da es keine andere Methode gibt, die damit was anfangen kann (und außerdem ist der Wert mehr oder weniger Zufall, …).

Code: Alles auswählen

        for self.path in self.verzeichnisse: # path solltest du nicht an sel binden
            for self.entry in os.listdir(self.path): # entry auch nicht.
                print os.path.join(self.path, self.entry)
Zuletzt geändert von nomnom am Freitag 26. April 2013, 18:02, insgesamt 1-mal geändert.
BlackJack

@Gary123456: Eine Klasse macht hier keinen Sinn. Wenn man eine Klasse hat, die nur eine echte Methode besitzt, dann kann man das in der Regel einfacher durch eine Funktion ausdrücken. Und sollte das auch tun.

`shasum()` ist keine echte Methode sondern nur eine Funktion die unnötigerweise in eine Klasse gesteckt wurde.
Gary123456
User
Beiträge: 318
Registriert: Dienstag 26. Februar 2013, 18:39

Das ist das Problem. Ich frag mich immer, wann eine Klasse sinnvoll ist.
Edit: Warum machst du path zu einem Attribut? Das ist doch unsinnig, da es keine andere Methode gibt, die damit was anfangen kann (und außerdem ist der Wert mehr oder weniger Zufall, …).
In Bayrisch: Des wor deppad von miar. Zufrieden? :lol:
Sirius3
User
Beiträge: 17844
Registriert: Sonntag 21. Oktober 2012, 17:20

Generatoren sind ganz einfach. Deine listen-Method wird zu

Code: Alles auswählen

def listen(directories):
        for path in directories:
            for entry in os.listdir(path):
                yield os.path.join(path, entry)
und im Hauptteil kannst Du dann mit einer for-Schleife die Dateienamen weiterverwenden:

Code: Alles auswählen

for filename in listen(["C:\\"]):
    print filename
Der Name der Variable »Klasse« ist zweifach schlecht: er ist großgeschrieben und er sagt nichts darüber aus, für was er verwendet wird.
Gary123456
User
Beiträge: 318
Registriert: Dienstag 26. Februar 2013, 18:39

Ich komme der Lösung immer näher :)
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

Gary123456 hat geschrieben:Ich komme der Lösung immer näher :)
Dazu fallen mir nur zwei Fragen ein:
- DER Lösung?
- Wirst Du Sie erreichen können oder Dich "nur" aufgrund der physischen Endlichkeit in diesem Raum-Zeit-Kontinuum einer für Dich akzeptablen Lösung nähern können?

*hier Paukenschlag oder irgendwas Dramatisches :shock:

Ok, war wohl doch zuviel Bier mit einem nicht halten wollendem unvollständigen Herr Turing :oops:
nezzcarth
User
Beiträge: 1651
Registriert: Samstag 16. April 2011, 12:47

Gary123456 hat geschrieben:Bedeutet, dass ich das alles per main() steuern soll? Und so bessere Kontrolle über Funktionen habe? Verstehe es immer noch nicht ganz ...
Eine wesentliche Eigenschaft von Python ist, dass viele Dinge, die in anderen Sprachen erzwungen werden, per Konvention geregelt sind. Es ist nicht unbedingt nötig, dass du dich an pep8 hälst, oder idiomatischen Code schreibst, damit deine Programme laufen.

So kannst du z.B. in Python einfach schreiben:

Code: Alles auswählen

for char in "Hello World": print(char)
während du beispielsweise in Pascal (das meist als nicht mehr zeitgemäß angesehen wird) zu soetwas genötigt würdest:

Code: Alles auswählen

program HelloWorld;
var     i: integer;
        msg: string;

begin
        msg := 'Hello World!';
        for i := 1 to length(msg) do writeln(msg[i])
end.
Hier wirst du dazu gewungen, über dein Programm auf eine bestimmte Weise nachzudenken und es in einer bestimmten Weise zu strukturieren - sonst passiert nichts. Besonders viel Spaß macht das nicht (hat vielleicht was von Basketball spielen mit Medizinbällen ;) )

Python erlaubt dir sehr viele Dinge zu tun, die - um beim Beispiel zu bleiben - in Pascal ausgeschlossen sind.
Trotzdem haben sich Regeln zum Umgang damit herausgebildet, die man befolgen sollte (außer man weiß genau, warum nicht). Dieses "__main__" Konstrukt ist ja schon ein Beispiel dafür: damit der Code läuft, ist es nicht zwinged erforderlich - aber in vielen Fällen absolut sinnvoll. Daher ist es ratsam, sich an solche Konventionen zu halten, auch wenn dir der Sinn vielleicht nicht unmittelbar ersichtlich ist.
Gary123456
User
Beiträge: 318
Registriert: Dienstag 26. Februar 2013, 18:39

Code: Alles auswählen

import os
import sha
import filecmp

def shasum(filepath, blocksize = 1024 * 1024): 
    h = sha.new()
    with open(filepath, "rb") as f:
        try:
            while True:
                part = f.read(blocksize)
                if not part:
                    break
                h.update(part)
        finally:
            f.close()   
            return h.hexdigest()


def listen(verzeichnisse):
    for path in verzeichnisse:
        for entry in os.listdir(path):
            yield os.path.join(path, entry)

def main():
    with open("Testdatei.txt", "w") as textdatei:
        verzeichnisse = ["C:\\"]     
        geschuetzt_files = ["C:\hiberfil.sys", "C:\pagefile.sys"]
        k = 0
        for files in listen(verzeichnisse):
            if os.path.isfile(files):
                if filecmp.cmp(files, geschuetzt_files[k]):
                    k += 1
                    if k > len(geschuetzt_files):
                        k = 0
                    else:
                        continue
                else:                       
                    print files
                
                    
        textdatei.close()
        #Code kommt noch!


if __name__ == "__main__":
    main()
        
        
Ich will jetzt zwei Dateien vergleichen. Dazu habe ich das Modul filecmp gefunden. Dokumentation auch schon gelesen. Nun versuche ich per Index die Elemte der Liste geschuetzte_files mit den gelisteten Files zu vergleichen. Dabei kommt immer der Fehler IndexError: ListIndex Out of range. Daher wollte ich abfragen, ob k größer als die Anzahl der Elemente der Liste ist. Wenn ja setze k wieder auf 0. Dennoch funktioniert der Code nicht. Am Code arbeite ich seit gestern Nachmittag und komme einfach nicht weiter. Wenn man statt k z.B. 0 einsetzt, wird logischerweise hiberfil.sys nicht mehr aufgelistet. (Teilerfolg!). Ist es ein Denkfehler? Oder habe ich mir das schon wieder zu kompliziert gemacht?

Code listet nur Dateien und keine Folder -> Das ist beabsichtigt!
Sirius3
User
Beiträge: 17844
Registriert: Sonntag 21. Oktober 2012, 17:20

Hallo Gary123456,

ich würde sagen, Denkfehler, aber woanders als Du denkst. Du mußt jeden Dateinamen mit allen Namen in der Liste » geschuetzt_files« vergleichen, ob er irgendwo vorkommt.
BlackJack

@Gary123456: `files` klingt nach Mehrzahl daran gebunden wird aber nur *ein* Datei*name*.

Wenn Du über `geschuetzt_files` (ebenfalls ein schlechter Name) iterieren willst, warum nimmst Du dann nicht ganz einfach eine ``for``-Schleife über die Elemente dieser Liste statt diesem reichlich komischen Code mit dem `k`, der so überhaupt keinen Sinn macht.

Ebenfalls sinnfrei ist die Datei `textdatei` (schlechter Name), die überhaupt nicht benutzt wird.
Gary123456
User
Beiträge: 318
Registriert: Dienstag 26. Februar 2013, 18:39

Wenn Du über `geschuetzt_files` (ebenfalls ein schlechter Name) iterieren willst, warum nimmst Du dann nicht ganz einfach eine ``for``-Schleife über die Elemente dieser Liste statt diesem reichlich komischen Code mit dem `k`, der so überhaupt keinen Sinn macht.
Das wäre auch mein erster Versuch gewesen. Leider gibt es dann, wo ich files printen lasse, die Dateinamen immer doppelt aus.
Ebenfalls sinnfrei ist die Datei `textdatei` (schlechter Name), die überhaupt nicht benutzt wird.
Um nicht immer diese textdatei öffnen zu müssen, habe ich print benutzt. Daher ist das meiner Sicht nach nicht sinnbefreit.

@Sirius3) Danke! Ich glaube ich habs verstanden!
Antworten