Python Script zum ändern von Dateiendungen

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.
korkak
User
Beiträge: 29
Registriert: Freitag 30. Dezember 2011, 19:44

naja, mir ist natürlich bewußt das ich noch viel lesen/lernen muss.
das programm an sich läuft ja jetzt eigentlich auch so wie es soll, jetzt interessiert mich einfach brennend wie man die tipps von hyperion umsetzen kann...
was ich bisher gelesen hatte ist halt, dass man mit "global" die variable mit allen modulen nutzen kann oder man schreibt die globale variablen in eine extra datei und importiert diese. ich verstehe einfach nur nicht wie ich das gleiche ergebnis mit der klasse
hinbekommen kann. :K
wenn mir da noch jemand mehr licht ins dunkel bringen könnte :)


ps: an den threads bin ich weiter dran, so leicht gebe ich nicht auf :D
korkak
User
Beiträge: 29
Registriert: Freitag 30. Dezember 2011, 19:44

so ich glaube ich habe das mit der klasse verstanden, bitte bestätigen :D

Code: Alles auswählen

import os, glob, sys
from PyQt4 import QtGui, QtCore, uic
 
class MeinDialog(QtGui.QDialog):
    
    names = []
    
    def __init__(self):
        QtGui.QDialog.__init__(self)
        self.ui = uic.loadUi("rename.ui", self)
        # Slots einrichten
        self.Eingabe.clicked.connect(self.onEingabe)
        self.Los.clicked.connect(self.onLos)
        self.Loeschen.clicked.connect(self.onLoeschen)
        self.Ende.clicked.connect(self.onEnde)
        
    def onEingabe(self): 
        # Daten auslesen 
        d = {}
        pfad = unicode(self.pfad.text())
        if not os.path.exists(pfad):
            self.ausgabe.append("Das Verzeichnis '%s' existiert nicht." % pfad)
        alt = unicode(self.alt.text())
        #global names
        MeinDialog.names = glob.glob(os.path.join(pfad, "*." + alt))
        self.ausgabe.append("Folgende Dateien wurden gefunden:")
        self.ausgabe.append("-----------------------------------------------")
        self.ausgabe.append("\n".join(MeinDialog.names))
        self.ausgabe.append("-----------------------------------------------")
 
    def onLoeschen(self):
        self.pfad.clear()
        self.alt.clear()
        self.neu.clear()
        
    def onLos(self):
        if MeinDialog.names:
            neu = unicode(self.neu.text())
            for name in MeinDialog.names:
                os.rename(name, os.path.splitext(name)[0]+'.'+neu)
            self.ausgabe.append("-----------------------------------------------")
            self.ausgabe.append("%d Dateien wurden umbenannt." % len(MeinDialog.names))            
                        
        else:
            self.ausgabe.append("Bitte zuerst ein Verzeichnis angeben!")
 
    def onEnde(self): 
        self.close()
 
app = QtGui.QApplication(sys.argv) 
dialog = MeinDialog() 
dialog.show() 
sys.exit(app.exec_())
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

korkak hat geschrieben:so ich glaube ich habe das mit der klasse verstanden, bitte bestätigen :D
Negativ!

Ich hatte es Dir doch oben schon einmal korrekt gezeigt... nach welchem Buch lernst Du denn? Woher hast Du das, was Du da jetzt gemacht hast?
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
korkak
User
Beiträge: 29
Registriert: Freitag 30. Dezember 2011, 19:44

hi hyperion,

kannst du bitte begründen warum mein vorgehen falsch ist? für mein verständsnis habe ich deinen vorschlag richtig umgesetzt. um besser nachvollziehen zu können warum ich dieser meinung bin, versuche ich die funktionsweise meiner gui zu erklären.

die gui hat 3 eingabefelder für pfad, alte endung und neue endung.
wenn man nun auf den button übernehmen(modul onEingabe) klickt wird die variable names, die jetzt nicht mehr mit global deklariert ist, sondern als attribut der klasse MeinDialog definiert ist, befüllt und eine meldung über die gefunden dateien wird in der gui ausgegeben.
wenn man nun den button umbenennen(modul onLos) klickt, greift das modul auf die variable names zu, benennt die dateien um und gibt eine meldung in der gui aus wieviele dateien umbenannt wurden.

für mich macht diese vorgehensweise sinn, falls es doch falsch sein sollte erkläre es bitte, ich möchte es doch lernen.


zu deiner frage, woher ich meine infos habe, ich lese im moment folgende seite:

http://www.python-kurs.eu/klassen.php


danke und gruß korkak
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

korkak hat geschrieben: zu deiner frage, woher ich meine infos habe, ich lese im moment folgende seite:

http://www.python-kurs.eu/klassen.php
Vergiss dieses Tutorial am besten - da steht jede Menge Mist drin! Erinnert mich auch irgend wie an das OpenBook... "Kontoklasse"... war mir doch so?

Benutze doch lieber mal das offizielle Tutorial, von mir aus auch die Übersetzung: tutorial.pocoo.org. Und schau Dir noch mal mein Beispiel an - das sind ja nur wenige Zeilen und dann vergleiche das mal mit Deiner Lösung. Du wirst definitiv einen Unterschied finden. Und diesen kannst Du auch durch das Tutorial nachvollziehen und verstehen.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
snafu
User
Beiträge: 6736
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Dein `name`-Attribut ist insofern nicht ganz korrekt gesetzt, weil man in den meisten Fällen ein Attribut auf Exemplar-Ebene und nicht auf der Klasse selbst nutzen möchte. Als kleine Veranschaulichung mal ein konstruiertes sinnloses Beispiel:

Code: Alles auswählen

>>> class NameManager(object):
...     names = []
...     def add_name(self, name):
...         self.names.append(name)
... 
>>> women = NameManager()
>>> women.add_name('Peggy')
>>> women.add_name('Sandra')
>>> women.names
['Peggy', 'Sandra']
>>> men = NameManager()
>>> men.add_name('Barney')
>>> men.add_name('Paul')
>>> women.names
['Peggy', 'Sandra', 'Barney', 'Paul']
Wie du siehts, führt dieser Ansatz zu vom Benutzer unerwartetem Verhalten. Abhilfe schafft Folgendes:

Code: Alles auswählen

>>> class CorrectNameManager(object):
...     def __init__(self):
...         self.names = []
...     def add_name(self, name):
...         self.names.append(name)
... 
>>> women = CorrectNameManager()
>>> women.add_name('Peggy')
>>> women.add_name('Sandra')
>>> women.names
['Peggy', 'Sandra']
>>> men = CorrectNameManager()
>>> men.add_name('Barney')
>>> men.add_name('Paul')
>>> women.names
['Peggy', 'Sandra']
>>> men.names
['Barney', 'Paul']
Mit "Exemplar" ist übrigens die Art von Entität (nenn ich jetzt mal so) gemeint, die als `women` bzw `men` genutzt wird. Also nicht das Klassenobjekt an sich, sondern eben das "Ding", worauf man irgendwelche Aktionen durchführen möchte.

Und falls das Vorgehen noch nicht so ganz klar geworden sein sollte: Klassenattribute sind quasi statisch, d.h. du kannst sie im Prinzip immer ändern. Selbst so etwas ginge:

Code: Alles auswählen

>>> class Foo(object):
...     bar = []
...     def give_bar(self):
...         return self.bar
... 
>>> foo = Foo()
>>> foo.give_bar()
[]
>>> foo2 = Foo()
>>> foo2.bar.append('spam')
>>> Foo.bar.append('eggs')
>>> foo.give_bar()
['spam', 'eggs']
An Klassenattributen kann also so ziemlich jeder nach Lust und Laune rumfummeln, auch wenn beim letzten Beispiel offenkundig schon ein gewisser Vorsatz vorliegen muss. In Python verbieten wir ja bekanntlich ungerne Dinge, sondern vertrauen eher darauf, dass der Benutzer schon keinen Mist machen wird. In der Realität kann aber zumindest das Beispiel mit den Männer- und Frauennamen durchaus vorkommen und dann für entsprechende Verwirrung (oder schlimmer) sorgen. Also sowas am Besten gar nicht erst angewöhnen, außer man braucht tatsächlich ein statisches Attribut (was aber eher selten vorkommt).
korkak
User
Beiträge: 29
Registriert: Freitag 30. Dezember 2011, 19:44

danke erst einmal für eure geduld, ihr seht schon mir fällt das thema nicht so leicht.

@hyperion, da hab ich ja wieder mal in klo gegriffen, beim versuch eine deutsche doku zu finden... ich fang nochmal von vorne an mit deinem link, danke.

@snafu, super erklärung, danke dir.
ich habe nun verstanden, dass statische variablen genauso beliebt sind wie die "global" funktion, sicherlich in einigen situationen hilfreich aber wenn es um kapselung in der OOP geht nicht geeignet.
mit women und men hast du zwei instanzen der klasse geschaffen, die unterschiedliche werte speichern können. bei mir will aber einfach nicht der groschen fallen, wie ich dies in meinem fall umsetzen kann....obwohl, ich schätze ich muss meine denkweise ändern, ich versuche die ganze zeit diesselbe variable mit 2 modulen zu nutzen, was in OOP ja nicht getan werden sollte. macht es mehr sinn, wenn ich mir die variable in den beiden modulen unabhängig voneinander zusammenbaue?


danke und gruß
korkak
Benutzeravatar
snafu
User
Beiträge: 6736
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Na, du legst die Liste für deine Namen halt in der `__init__`-Methode des Widgets an und nicht auf Klassenebene.
korkak hat geschrieben:ich versuche die ganze zeit diesselbe variable mit 2 modulen zu nutzen, was in OOP ja nicht getan werden sollte.
Warum sollte das nicht getan werden? :o
korkak
User
Beiträge: 29
Registriert: Freitag 30. Dezember 2011, 19:44

ich dachte von wegen kapselung in oop, ich glaube ich seh den wald vor lauter bäumen nicht mehr...

das ganze sieht dann so aus oder sollte ich besser noch im init teil eine instanz der klasse erzeugen und darüber auf die variable zugreifen?

Code: Alles auswählen

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

import os, glob, sys
from PyQt4 import QtGui, QtCore, uic
class MeinDialog(QtGui.QDialog):
    
    def __init__(self):
        self.names = []
        QtGui.QDialog.__init__(self)
        self.ui = uic.loadUi("rename.ui", self)
        # Slots einrichten
        self.Eingabe.clicked.connect(self.onEingabe)
        self.Los.clicked.connect(self.onLos)
        self.Loeschen.clicked.connect(self.onLoeschen)
        self.Ende.clicked.connect(self.onEnde)
        
    def onEingabe(self): 
        # Daten auslesen und gefundene Dateien ausgeben
        d = {}
        pfad = unicode(self.pfad.text())
        if not os.path.exists(pfad):
            self.ausgabe.append("Das Verzeichnis '%s' existiert nicht." % pfad)
        alt = unicode(self.alt.text())
        MeinDialog.names = glob.glob(os.path.join(pfad, "*." + alt))
        self.ausgabe.append("Folgende Dateien wurden gefunden:")
        self.ausgabe.append("-----------------------------------------------")
        self.ausgabe.append("\n".join(MeinDialog.names))
        self.ausgabe.append("-----------------------------------------------")

    def onLoeschen(self):
        #Eingabefelder Löschen
        self.pfad.clear()
        self.alt.clear()
        self.neu.clear()
        
    def onLos(self):
        #Dateien umbenennen
        neu = unicode(self.neu.text())
        for name in MeinDialog.names:
            os.rename(name, os.path.splitext(name)[0]+'.'+neu)
        self.ausgabe.append("-----------------------------------------------")
        self.ausgabe.append("%d Dateien wurden umbenannt." % len(MeinDialog.names))

    def onEnde(self):
        #Gui schließen
        self.close()

app = QtGui.QApplication(sys.argv) 
dialog = MeinDialog() 
dialog.show() 
sys.exit(app.exec_())
BlackJack

@korkak: Du hast es immer noch nicht verstanden, denn Du verwendest immer noch ein *Klassenattribut* für die Namen.
Benutzeravatar
snafu
User
Beiträge: 6736
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Und ich frage mich auch, wo `ausgabe` plötzlich herkommt. Nach einem Widget des `ui`-Erzeugers sieht mir das nämlich nicht aus (wegen `.append()`).

Weiterhin verweise ich an die betreffende Stelle im bereits zuvor genannten deutschen Python-Tutorial (http://tutorial.pocoo.org/classes.html). Es bringt einfach nichts, das jemandem zu erklären, der quasi noch bei Null steht im Hinblick auf das Thema "Klassen" und mehr oder weniger bloß wild rumprobiert, um irgendwie ans Ziel zu kommen.
Antworten