Baumstruktur

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
HarryH
User
Beiträge: 266
Registriert: Freitag 23. Mai 2003, 09:08
Wohnort: Deutschland

Mittwoch 15. Dezember 2004, 10:05

Hallo,

Ich suche einen Tip, eine Ordnerstruktur mit Unterordnern und Dateien in einer Baumstruktur wiederzugeben.
Funktionen wie Umbenennen, Kopieren, Löschen sollten mit diesem Objekt schnell und sicher zu erledigen sein.
Ich dachte an ein in sich verschachteltes Dictionary oder an ein Dictionary in dem jeder Pfad als Schlüssel abgespeichert wird.

Habt ihr bessere Ideen? Ich wäre dankbar für Anregungen!
Gruß, Harry
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Mittwoch 15. Dezember 2004, 10:40

An etwas änliches arbeite ich auch. Eine Backup-Datenbank...

Die Daten einer CD speichere ich in zwei Listen...
Eine für Verzeichnisse und eine für Dateien.
Jedes Verzeichniss und jede Datei bekommt eine ID...

Bei jedem Verzeichniss ist die ID des Parent-Verz. angegeben. Bei jeder Datei die ID des Verz. in dem die Datei liegt...

Aufbau der Verz.-Liste:

Code: Alles auswählen

0 - ID         
1 - parent     
2 - name       
3 - size       
4 - description
5 - attrib     
6 - createdate 
7 - lastdate   
8 - moddate    
9 - depth      
Aufbau der Datei-Liste:

Code: Alles auswählen

0 - ID         
1 - parent     
2 - name       
3 - size       
4 - description
5 - attrib     
6 - createdate 
7 - lastdate   
8 - moddate    
9 - depth      
Anmerkungen:
Die ID wird für jeder Verz. und jede Datei um eins erhöht und gilt dabei als ID für
Verz. und Dateien gleichzeitig.

Bsp.:
ID | Verz.+Dateien
0 | \
1 | |--UnterVerz\
2 | |- Datei1.txt
3 | `- Datei2.txt

depth
-----
Bei Verz. gilt für das ROOT-Verzeichnis und die ersten UnterVerz. (also die Verz. im ROOT, ohne deren UnterVerz.) beide "depth = 0".
Erst das UnterVerz. eines UnterVerz. des ROOT erhält "depth = 1"

Bsp.:
depth | Verz.Struktur
0 | \ <- (Root-Verz.)
0 | |--UnterVerz1\
1 | `--UnterVerz2\

Für Dateien gilt dagegen die Regel "depth = Anzahl der Verz.". Also haben Dateien im ROOT-Verz. "depth = 0", Dateien im ersten
UnterVerz. (UnterVerz1\*.*) "depth = 1", Dateien im zweiten UnterVerz. (UnterVerz1\UnterVerz2\*.*) gilt "depth = 2" usw.

Weiß allerdings nicht, ob ich die Datenstruktur beibehalte... Denn diese ist zwar ideal für eine normale Datenbank, aber vielleicht nutze ich leiber eine OODB s. http://python.sandtner.org/viewtopic.php?t=2412
HarryH
User
Beiträge: 266
Registriert: Freitag 23. Mai 2003, 09:08
Wohnort: Deutschland

Mittwoch 15. Dezember 2004, 10:58

Hi Jens,

Also so ganz blicke ich da nicht durch. Ich welchem Zusammenhang stehen die einzelnen Listen zueinander? Sind sie in einem Dictionary abgespeichert? Und wie greifst du auf die Informationen der Dateien oder Ordner zu wenn du nur die Pfadangabe hast?
Gruß, Harry
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Mittwoch 15. Dezember 2004, 11:06

Nein, ich habe eine Klasse, in dem diese beiden Listen über Funktionen befüllt und abgefragt werden können...

Ich weiß nicht ob du damit was anfangen kannst, aber hier mal mein Stand der Dinge:

Code: Alles auswählen

#!/usr/bin/python
# -*- coding: cp1252 -*-

__version__="0.0.3"

import os.path, time, sys

# Damit "Unterroutinen" gefunden werden, wird der Pfad erweitert:
sys.path.append("Routinen")

import FileVersionInfo
import REGinfo

class DiscData:
    """
    =====================
     DirInfo - Type:List
    =====================
    Jeder Verzeichnis ist ein Eintrag als Liste mit folgenden Informationen:

        0 - ID              ('NUMBER', 11, 10, 0, 0, 1)     PathWalkID - Nummer auch für Dateien!
        1 - parent          ('NUMBER', 11, 10, 0, 0, 1)     ID-Nr. des nächst höheren Verzeichnisses
        2 - name            ('STRING', 255, 255, 0, 0, 1)
        3 - size            ('NUMBER', 11, 10, 0, 0, 1)
        4 - description     ('STRING', 255, 255, 0, 0, 1)
        5 - attrib          ('STRING', 10, 10, 0, 0, 1)
        6 - createdate      ('DATE', 19, 19, 0, 0, 1)
        7 - lastdate        ('DATE', 19, 19, 0, 0, 1)
        8 - moddate         ('DATE', 19, 19, 0, 0, 1)
        9 - depth           ('NUMBER', 6, 5, 0, 0, 1)

    Bsp (zwei Einträge):
    (1,  0, 'R:', 576814470, None, 'D',  <DbiDate object at 0x008AE060>, <DbiDate object at 0x008AE050>, <DbiDate object at 0x008AE070>, 0)
    (18, 1, 'IE5', 79407911, None, 'DR', <DbiDate object at 0x008AE080>, <DbiDate object at 0x008AE090>, <DbiDate object at 0x008AE0A0>, 0)

    ======================
     FileInfo - Type:List
    ======================
    Jede Datei ist ein Eintrag in Form einer Liste mit folgenden Informationen:

        0 - ID              ('NUMBER', 11, 10, 0, 0, 1)     PathWalkID, Nummer auch für Verzeichnisse!
        1 - parent          ('NUMBER', 11, 10, 0, 0, 1)     ID-Nr. des Verz. in dem die Datei liegt!
        2 - name            ('STRING', 255, 255, 0, 0, 1)
        3 - size            ('NUMBER', 11, 10, 0, 0, 1)
        4 - description     ('STRING', 255, 255, 0, 0, 1)
        5 - attrib          ('STRING', 10, 10, 0, 0, 1)
        6 - createdate      ('DATE', 19, 19, 0, 0, 1)
        7 - lastdate        ('DATE', 19, 19, 0, 0, 1)
        8 - moddate         ('DATE', 19, 19, 0, 0, 1)
        9 - depth           ('NUMBER', 6, 5, 0, 0, 1)

    Bsp (zwei Einträge):
    (3, 1, 'AUTORUN.INF', 1838, None, 'R', <DbiDate object at 0x008AE060>, <DbiDate object at 0x008AE050>, <DbiDate object at 0x008AE070>, 0)
    (4, 1, 'DATA1.MSI', 2348544, None, 'R', <DbiDate object at 0x008AE080>, <DbiDate object at 0x008AE090>, <DbiDate object at 0x008AE0A0>, 0)


    *************
     Anmerkungen
    *************

        PathWalkID
        ----------
    Die ID wird für jeder Verz. und jede Datei um eins erhöht und gilt dabei als ID für
    Verz. und Dateien gleichzeitig.

    Bsp.:
        ID | Verz.+Dateien
         0 |  \
         1 |  |--UnterVerz\
         2 |      |- Datei1.txt
         3 |      `- Datei2.txt


        depth
        -----
    Bei Verz. gilt für das ROOT-Verzeichnis und die ersten UnterVerz. (also die Verz. im ROOT, ohne deren UnterVerz.) beide "depth = 0".
    Erst das UnterVerz. eines UnterVerz. des ROOT erhält "depth = 1"

    Bsp.:
        depth | Verz.Struktur
          0   |  \                       <- (Root-Verz.)
          0   |  |--UnterVerz1\
          1   |         `--UnterVerz2\

    Für Dateien gilt dagegen die Regel "depth = Anzahl der Verz.". Also haben Dateien im ROOT-Verz. "depth = 0", Dateien im ersten
    UnterVerz. (UnterVerz1\*.*) "depth = 1", Dateien im zweiten UnterVerz. (UnterVerz1\UnterVerz2\*.*) gilt "depth = 2" usw.

    """
    def __init__( self ):
        self.Disc = []
        self.MyFileTypeInfo = REGinfo.FileTypeInfo()

    ###
    ### Funktionen zum hinzufügen von Daten
    ###

    def newDisc( self, ID ):
        self.Disc.append( ID )
        self.currentDisc = ID

        # Liste für die Verzeichniss-Informationen
        self.DirInfo = []
        self.currentVerzID = 0

        # Liste der Datei-Daten
        self.FileInfo = []

        # Informationen zum Dateityp, Verknüpfung mit Programmen
        self.ExtInfo = {}


    def newDirectory( self, PathWalkID, DirName, DirStat ):
        # Aktuelles Verz.ID für Dateien speichern, damit die Datei-Funktion auch weiß, aus
        # welchem Verz. die Dateien stammen
        self.currentVerzID = PathWalkID

        # Pfad aufsplitten in Laufwerk und Verz.
        DriveLetter, DirName = os.path.splitdrive( DirName )

        if DirName == "":   ### Aktuelles Verzeichnis ist das Hauptverzeichniss

            # Laufwerk = Root-Verz als ersten Eintrag in der DirInfo eintragen
            ParentDirID = 0
            currentDirName = DriveLetter
            self.DirDepth = 0

        else:               ### Normales Verzeichnis

            # Liste erstellen mit allen Verzeichnissen
            # Bsp.: ['r:', 'Verz', 'UnterVerz']
            DirList = [DriveLetter] + DirName.split(os.sep)
            currentDirName = DirList[-1]

            # Verzeichnis Tiefe: Root + erstes Unterverz = 0
            # auch genutzt für Dateien!
            self.DirDepth = len(DirList) - 2

            # vorletzte Verzeichniss ist das Parent-Verz.
            ParentDirName = DirList[-2]

            # Hohlt ID des Parent-Verz.
            ParentDirID = self.getDirIDbyName( ParentDirName )

        CreationTime        = DirStat.st_ctime
        LastAccess          = DirStat.st_atime
        LastModification    = DirStat.st_mtime

        # Stellt den Eintrag für das aktuelle Verzeichniss zusammen
        Info = [
            PathWalkID,         # 0 - ID
            ParentDirID,        # 1 - parent
            currentDirName,     # 2 - name
            0,                  # 3 - size
            "",                 # 4 - description
            "",                 # 5 - attrib
            CreationTime,       # 6 - createdate
            LastAccess,         # 7 - lastdate
            LastModification,   # 8 - moddate
            self.DirDepth       # 9 - depth
        ]

        if ParentDirID == 0:    ### Root-Verzeichnis
            # Damit die "FileDepth" für Dateien im Root-Verzeichniss stimmt, wird
            # self.DirDepth manipuliert
            self.DirDepth = -1

        self.DirInfo.append( Info )

    def newFile( self, PathWalkID, FileName, FileStat ):
        """
        Eine neue Datei aufnehmen

        Die ID der Datei ist die PathWalkID, die auch glaichzeitig für Verzeichnisse ist, aber nicht für
        den Zusammenhang zwischen Verzeichnis <-> Datei!!! Dafür ist die "parent"-ID zuständig!!! Sie
        gibt die ID-Nr. des Verzeichnisses an, in dem die Datei liegt.

        """

        # ID zur verknpüpfung zwischen Datei <-> Endungs-Information
        ExtInfoID = self.newExtInfo( FileName )

        self.FileInfo.append(
            {
                "ID"            : PathWalkID,
                "parent"        : self.currentVerzID,
                "name"          : FileName,
                "size"          : FileStat.st_size,     # FileSize
                "description"   : "",
                "attrib"        : "",
                "createdate"    : FileStat.st_ctime,    # CreationTime
                "lastdate"      : FileStat.st_atime,    # LastAccess
                "moddate"       : FileStat.st_mtime,    # LastModification
                "depth"         : self.DirDepth + 1,    # FileDepth
                "extInfoID"     : ExtInfoID
            }
        )


    def newExtInfo( self, FileName ):
        """
        wird von self.newFile() aufgerufen!

            DateiTyp Informationen über Verknüpfung und Programm-Versionen

        benötigt Modul: REGinfo und FileVersionInfo

        0 - Ext             Dateiendung
        1 - TypeInfo        Allgemeine Beschreibung des DateiTyps
        2 - Program         Programm mit dem der DateiTyp verknüpft ist
        3 - CompanyName        |-- Firma
        4 - FileDescription    |--
        5 - FileVersion        |-- Version
        6 - LegalCopyright     `-- Copyright

        self.ExtInfo

        """
        FileExt = os.path.splitext( FileName )[1]
        if FileExt == "": return -1

        if self.ExtInfo.has_key(FileExt):
            return self.ExtInfo[FileExt]["ID"]

        ExtInfo = self.MyFileTypeInfo.getInfo( FileExt )
        #~ "Type"     - DateiTyp-Kennung (wie Win-Befehl "assoc" herrausliefert)
        #~ "TypeInfo" - Allgemeine Beschreibung des DateiTyps
        #~ "Program"  - direkter Pfad zur Datei (sofern existiert)

        if ExtInfo != None:#and ExtInfo.has_key("Program"):
            print FileExt, ExtInfo

        DescItems = ["CompanyName", "FileDescription", "FileVersion", "LegalCopyright"]
        FileInfo = FileVersionInfo.getFileVerInfo( ExtInfo["Program"], DescItems )
        if FileInfo:
            for i in FileInfo:
                print i,"-", FileInfo[i]
        else:
            print "- Keine DateiInformation vorhanden -"

        print

        #~ self.ExtInfo
        #~ print Ext


    ###
    ### allgemeine Funktionen zum Auslesen der Daten, die nicht
    ### konkreten Problemlösungen sind

    def getItemsByItem( self, List, SearchNr, SearchValue, SourceNr ):
        """
        Liefert eine Liste aller Werte in der >SourceNr<-Spalte, wenn in
        der >SearchNr<-Spalte der Wert = >SearchValue< ist.
        Das ganze wird in der >List< durchgeführt.
        Bsp.
          | 0  | 1  | 2
        ----------------
        0 | A1 | B1 | C1
        1 | A2 | B1 | C2
        2 | A3 | B1 | C3

        getItemsByItem( XXX, 0, "A2", 2) => ["C2"]
        getItemsByItem( XXX, 1, "B1", 1) => ["A1","A2","A3"]
        """
        Results = []
        for i in List:
            if i[SearchNr] == SearchValue:
                Results.append( i[SourceNr] )
        return Results

    def getItemByItem( self, List, SearchNr, SearchValue, SourceNr ):
        """
        Im Prinzip die gleiche Funktion wie getItemsByItem()!
        Jedoch wird beim ersten Treffer abgebrochen.
        """
        for i in List:
            if i[SearchNr] == SearchValue:
                return i[SourceNr]

    ###
    ### Funktionen zum auslesen der Daten
    ###

    def getVerzFromIDlist( self, DirIDlist ):
        """
        Liefert eine Liste der VerzNamen von der >DirIDlist< zurück.
        Wird bei fullPath() verwendet.
        """
        DirList = []
        for DirID in DirIDlist:
            DirList.append( getItemByItem( self.DirInfo, 1, DirID, 2) )
        print "DirList:",DirList
        return DirList

    def getFilesByDirID( self, DirID ):
        """
        Liefert eine Liste aller Datei-IDs zurück, die in dem Verzeichnis mit dem
        >DirID< sind, zurück.
        """
        return self.getItemListByItemValue( self.FileInfo, "ID", DirID, "parent" )

    def getDirIDbyName( self, DirName ):
        """
        Liefert die ID des ersten Verz. mit dem Namen >DirName< zurück
        Wird z.B. von newDirectory() benötigt
        """
        for i in self.DirInfo:
            currentDirName = i[2]
            if currentDirName == DirName:
                return i[0]
        print ">Fehler! [%s] nicht gefunden!" % DirName


    def getfullPathByDirID( self, DirID ):
        """
        Liefert den kompletten Pfad eines Verzeichnisses zurück, in dem
        die Parent-Verkettung vollständig aufgelöst wird.
        """
        PathIDs = []
        while 1:
            PathIDs.append( DirID )

            # DirID des Parent-Verzeichnisses:
            DirID = self.getItemByItem( self.DirInfo, 1, DirID, 0 )

            if ID==0: break

        # ID-Liste umkehren
        PathIDs.reverse()

        VerzListe = self.getVerzFromIDlist( PathIDs )
        print "\\".join(VerzListe)


    ###
    ### Hilfsfunktionen
    ###


    def getMaxDirDepth( self ):
        """
        Liefert den höchsten "depth"-Wert für Verz. zurück
        Wird von MakeDirInfoComplete() gebraucht
        """
        MaxDirDepth = 0
        for i in self.DirInfo:
            if i[9]>MaxDirDepth:
                MaxDirDepth = i[9]
        return MaxDirDepth


    def MakeDirInfoComplete( self ):
        """
        Addiert alle Dateigrößen
        """
        print "="*79

        for i in self.DirInfo[::-1]:
            print ">",i[2]
            DirID = i[0]
            print DirID

            # BytesListe, jeder Datei in dem aktuellen Verzeichniss:
            BytesList = self.getItemListByItemValue( self.FileInfo, "size", DirID, "parent" )

            AllBytes = 0
            for Bytes in BytesList:
                AllBytes += Bytes

            print AllBytes


            print self.getFilesByDirID( DirID )

        print "--XXX"

    def getItemListByItemValue( self, Liste, getKey, filterValue, filterKey ):
        """
        Gibt eine gefilterte Liste aus einer >Liste<, die ein Dict beinhaltet, zurück.

        Bsp "Liste":
        L=[
            { "item1":"1"  , "item2":"2"  }
            { "item1":"10" , "item2":"20" }
            { "item1":"100", "item2":"200" }
            { "item1":"33" , "item2":"20" }
        ]
        getItemListByItemValue(
            Liste       = L,
            getKey      = "item1",
            filterValue = "20"
            filterKey   = "item2"
        )
        Ergebnis-Liste:
            [ "10", "33" ]
        """
        result = []
        for i in Liste:
            if i[filterKey] == filterValue:
                result.append( i[getKey] )
        return result

    ###
    ### Debug-Funktionen:
    ###

    def dumpDirData( self ):
        print "-"*79
        print "Disc:",self.Disc
        for i in self.DirInfo:
            print i
        print "-"*79

    def dumpFileData( self ):
        print "-"*79
        print "Disc:",self.Disc
        for i in self.FileInfo:
            print i, self.FileInfo[i]
        print "-"*79




def getDiscID( DriveLetter ):
    from os import popen

    shell = popen( "dir %s:" % DriveLetter )
    DiscID = shell.readlines()[1].split(":")[1].strip()
    shell.close()

    DiscID = DiscID[:4]+DiscID[5:] # MittelStrich entfernen

    return DiscID






def GetData( PathWalkID, dirname, FileNameList ):
    if PathWalkID[0]>100: return

    PathWalkID[0] += 1

    print ">",PathWalkID[0],dirname
    DirStat = os.stat( dirname+"\\" )
    MyDiscData.newDirectory( PathWalkID[0], dirname, DirStat )

    for FileName in FileNameList:

        CompleteFilePath = dirname+os.sep+FileName

        if os.path.isfile( CompleteFilePath ):

            #~ print CompleteFilePath

            PathWalkID[0] += 1

            FileStat = os.stat( CompleteFilePath )
            MyDiscData.newFile( PathWalkID[0], FileName, FileStat )




#~ time.strftime("%d.%m.%Y - %H:%M:%S",time.localtime(Datum))



MyDiscData = DiscData()

DriveLetter = "r"
DiscID = getDiscID( DriveLetter )
MyDiscData.newDisc( DiscID )

DiscPath = DriveLetter+":"

PathWalkID = [0]
os.path.walk( DiscPath, GetData, PathWalkID)

#~ MyDiscData.dumpFileData()

MyDiscData.MakeDirInfoComplete()

#~ MyDiscData.dumpDirData()
Das ganze ist noch wirklich Pre-Beta ;) z.B. ist die Funktion MakeDirInfoComplete nicht wirklich fertig...
Jetzt nutze ich os.path.walk(), aber einfachere ist os.walk()...

Es ist also noch viel zu tun...

Außerdem ist dort auch verweise zu FileVersionInfo und REGinfo... Aber die kannst du vielleicht einfach ausklammern...

Mir ist auch aufgefallen, das ich im Prinzip einige Sachen direkt in eine DB schreiben und "bearbeiten" könnte... Denn irgendwie baue ich damit fast eine kleine DB selber... Aber da ich mich noch nicht auf eine bestimmten DB festgelegt hab, kann ich z.Z. nicht recht weiter machen...
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Mittwoch 15. Dezember 2004, 15:07

Hi HarryH,

das ist so eine Aufgabenstellung, die so richtig nach OOP schreit :)

Ich umreisse mal grob, wie ich das lösen würde.

1. Eine Basisklasse 'Node' erstellen. Diese bekommt als Attribute den Namen und den Parent, und die Methoden zum umbenennen, kopieren und löschen.
2. Davon eine Klasse 'Folder' ableiten, zum einfachen implementieren von Dictionaryfunktionalität kann die Klasse Folder auch gleichzeitig von dict abgeleitet sein.
3. Noch eine Klasse 'Entry' die dann die Daten enthält, auch abgeleitet von 'Node'.
4. Von 'Folder' würde ich auch noch eine Klasse 'Root' ableiten, in der die Funktionen zum löschen und umbenennen deaktiviert werden.

Beim Umbenennen muss dann in der Methode von Node einfach der Name von der Node-Instanz geändert und im Parent der entsprechenden Eintrag gelöscht und mit dem neuen Namen neu eingefügt werden. Was durch das Attribut Parent geschehen kann. Auch kann '__getitem__' in Folder so geändert werden, daß auch Pfade übergeben werden können und diese recursiv aufgelöst werden.


Gruß

Dookie
[code]#!/usr/bin/env python
import this[/code]
HarryH
User
Beiträge: 266
Registriert: Freitag 23. Mai 2003, 09:08
Wohnort: Deutschland

Donnerstag 16. Dezember 2004, 13:09

Hallo,

Hier mal ein Code, in dem die Treestructur in einem verschachtelten Dictionary aufgebaut ist.

Meldet euch bitte ob der Ansatz richtig ist und wenn Fehler gefunden werden.

Code: Alles auswählen

import os
import copy

class Dict_Tree:
    def __init__(self, d = {}):
        """
        d = Dicionary, that will representing the treestructur

        """
        self.dict_obj = d
        self.folder_id = 1
        self.file_id = 2


    def GetFolderData(self, path):
        """
        Get data from the folderpath
        path = list or tuple with items or path

        """
        dic = self.__GetData(path)
        if dic:
            if self.folder_id in dic:
                return dic[self.folder_id]

    def GetFileData(self, path):
        """
        Get data from the filepath
        path = list or tuple with items or path

        """
        dic = self.__GetData(path)
        if dic:
            if self.file_id in dic:
                return dic[self.file_id]

    def GetPathFolders(self, path):
        """
        Get all underroots from the path, when it is a dictionary
        path = list or tuple with items or path

        """
        path = self.ConvertPathToItemlist(path)
        dic = self.__GetData(path)
        if dic and type(dic) == dict:
            folderlist = []
            for i in dic:
                if type(dic[i]) == dict and not self.file_id in dic[i]:
                    folderlist.append(i)
            return folderlist
        else:
            return []

    def GetPathFiles(self, path):
        """
        Get all files from the path, when it is a dictionary
        path = list or tuple with items or path

        """
        path = self.ConvertPathToItemlist(path)
        dic = self.__GetData(path)
        if dic and type(dic) == dict:
            filelist = []
            for i in dic:
                if type(dic[i]) == dict and self.file_id in dic[i]:
                    filelist.append(i)
            return filelist
        else:
            return []

    def SetFolderData(self, path, data = None):
        """
        Set data for the folder
        path = list or tuple with items or path that will be set
        data = The data to set for the folder

        """
        path = self.ConvertPathToItemlist(path) + [self.folder_id]
        return self.__SetData(path, data)


    def SetFileData(self, path, data = None):
        """
        Set data for the file
        path = list or tuple with items or path that will be set
        data = The data to set for the file

        """
        path = self.ConvertPathToItemlist(path) + [self.file_id]
        return self.__SetData(path, data)


    #***************#
    #Privat methods #
    #***************#

    def __GetData(self, path):
        """
        Get the data from the path
        path = list or tuple with items or path

        """
        path = self.ConvertPathToItemlist(path)
        if self.ExistPath(path):
            dic = self.dict_obj
            for key in path:
                dic = dic[key]
            return dic

    def __SetData(self, path, data = None):
        """
        Set a path and her data or overwrite an existing pathdata
        path = list or tuple with items or path that will be set
        data = data for the path. It can be every object

        """
        path = self.ConvertPathToItemlist(path)
        if path:
            dic = self.dict_obj
            for key in path[:-1]:
                dic.setdefault(key, {})
                dic = dic[key]
            if path[-1] in dic and type(data) == dict:
                dic[path[-1]].update(data)
                return True
            else:
                dic[path[-1]] = data
                return True


    #*************#
    #Test methods #
    #*************#

    def ExistPath(self, path):
        """
        Test the existence from the path
        path = list or tuple with items or path

        """
        path = self.ConvertPathToItemlist(path)
        dic = self.dict_obj
        test = True
        for key in path:
            if type(dic) == dict and key in dic:
                dic = dic[key]
            else:
                test = False
                break
        return test

    def ConvertPathToItemlist(self, path):
        """
        Convert path to Itemlist
        path = list or tuple with items or path

        """
        if type(path) == str:
            if os.sep != "/":
                path = path.replace(os.sep, "/").strip("/")
            return  path.split("/")
        elif type(path) == list:
            return path
        elif type(path) == tuple:
            return list(path)
        else:
            raise TypeError, 'Requires list, tuple or string'


    #*****************#
    # Spezial methods #
    #*****************#

    def RenamePath(self, path, newpath):
        """
        Rename a path
        path =    list or tuple with items or path that will be rename
        newpath = New name for the path. It can be a list or tuple with items or path

        """
        path = self.ConvertPathToItemlist(path)
        newpath = self.ConvertPathToItemlist(newpath)
        if self.ExistPath(path) and path and newpath and path != newpath:
            dic = self.dict_obj
            for key in path[:-1]:
                dic = dic[key]
            old = dic.pop(path[-1])
            self.__SetData(newpath, old)
            return True

    def CutPath(self, path, newpath = None):
        """
        Cut a path
        path =    list or tuple with items or path that will be cut
        newpath = list or tuple with items or path that will be insert the cutpath

        """
        path = self.ConvertPathToItemlist(path)
        if self.ExistPath(path) and path != newpath:
            if newpath:
                newpath = self.ConvertPathToItemlist(newpath)
                return self.RenamePath(path, newpath)
            else:
                return self.__GetData(path)

    def CopyPath(self, path, newpath = None):
        """
        Copy a path
        path =    list or tuple with items or path that will be copy
        newpath = list or tuple with items or path that will be insert the copypath

        """
        path = self.ConvertPathToItemlist(path)
        if self.ExistPath(path) and path != newpath:
            if newpath:
                newpath = self.ConvertPathToItemlist(newpath)
                return self.__SetData(newpath, copy.deepcopy(self.__GetData(path)))
            else:
                return copy.deepcopy(self.__GetData(path))

    def InsertPath(self, insertpath, data):
        """
        Insert data in path
        insertpath = list or tuple with items or path
        data =       The data to insert in the insertpath

        """
        return self.__SetData(insertpath, data)

    def DelPath(self, path):
        """
        Delete a path
        path = list or tuple with items or path

        """
        path = self.ConvertPathToItemlist(path)
        if self.ExistPath(path) and path:
            dic = self.dict_obj
            for key in path[:-1]:
                dic = dic[key]
            del dic[path[-1]]
            return True
Die Daten werden folgendermaßen gesetzt:

Code: Alles auswählen

folderlist = [...]
filelist = [...]
tree = Dict_Tree()

for i in folderlist:
    tree.SetFolderData(i)

for i in filelist:
    tree.SetFileData(i)
Gruß, Harry
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Donnerstag 16. Dezember 2004, 13:16

Code: Alles auswählen

    def ExistPath(self, path):
        """
        Test the existence from the path
        path = list or tuple with items or path

        """
        path = self.ConvertPathToItemlist(path)
        dic = self.dict_obj
        test = True
        for key in path:
            if type(dic) == dict and key in dic:
                dic = dic[key]
            else:
                test = False
                break
        return test
Warum nicht so:

Code: Alles auswählen

    def ExistPath(self, path):
        """
        Test the existence from the path
        path = list or tuple with items or path

        """
        path = self.ConvertPathToItemlist(path)
        dic = self.dict_obj
        test = True
        for key in path:
            if type(dic) == dict and key in dic:
                dic = dic[key]
            else:
                return False

Außerdem wie ist folderlist und filelist Aufgebaut? Ich meine, wo entsteht die beziehung zwischen den Beiden, also in welchen Verz. eine Datei liegt usw.
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Donnerstag 16. Dezember 2004, 13:22

Weil dein Code nie True zurückgeben würde, sondern höchstens None?
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Donnerstag 16. Dezember 2004, 13:23

Ach das hab ich garnicht gesehen, aber was ist mit dem:

Code: Alles auswählen

    def ExistPath(self, path):
        """
        Test the existence from the path
        path = list or tuple with items or path

        """
        path = self.ConvertPathToItemlist(path)
        dic = self.dict_obj
        for key in path:
            if type(dic) == dict and key in dic:
                dic = dic[key]
            else:
                return False
        return True
So hat man sich die test-Variable eingespart
HarryH
User
Beiträge: 266
Registriert: Freitag 23. Mai 2003, 09:08
Wohnort: Deutschland

Donnerstag 16. Dezember 2004, 13:33

Hallo,

Ich habe selbst auch noch einen Fehler entdeckt.

Neuer Code:

Code: Alles auswählen

def ConvertPathToItemlist(self, path):
        """
        Convert path to Itemlist
        path = list or tuple with items or path

        """
        if type(path) == str:
            if os.sep != "/":
                path = path.replace(os.sep, "/")
            path = path.strip("/")
            if path:
                return  path.split("/")
            else:
                return []
        elif type(path) == list:
            return path
        elif type(path) == tuple:
            return list(path)
        else:
            raise TypeError, 'Requires list, tuple or string'
Zu der letzten Frage von Jens:
Filelist und Folderlist werden durch self.folder_id und self.file_id voneinandner unterschieden. Existiert weder die eine noch die andere in einem "Verzeichnis" wird das Objekt als Folder erkannt.

Die self.folder_id und self.file_id sind gleichzeitig die Schlüssel für die Daten zu dem jeweiligen Folder- oder File-Objekt.
Gruß, Harry
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Donnerstag 16. Dezember 2004, 14:00

Was ich ehr meinte, wie sieht die Datenstruktur aus... Du wolltest doch "Ordnerstruktur mit Unterordnern und Dateien in einer Baumstruktur" festhalten...
Wenn man jetzt deine Klasse mit den Daten von os.walk() füllen will, wie geht das?

Einfach so:

Code: Alles auswählen

tree = Dict_Tree()
for root, folderlist, filelist in os.walk(pfad):
    for i in folderlist:
        tree.SetFolderData(i)
    
    for i in filelist:
        tree.SetFileData(i) 
EDIT: Hab gerade gesehen, so ist's wohl gedacht... Und wie bekomme ich die Daten wieder herraus?
HarryH
User
Beiträge: 266
Registriert: Freitag 23. Mai 2003, 09:08
Wohnort: Deutschland

Donnerstag 16. Dezember 2004, 14:16

Hi,

Nein es geht so:

Code: Alles auswählen

folder = r"D:\Python"
tree = Dict_Tree()

for root, dirs, files in os.walk(folder):
    #search files
    for file in files:
        file = os.path.join(root, file)
        tree.SetFileData(file)
    #search folder
    for dir in dirs:
        dir = os.path.join(root, dir)
        tree.SetFolderData(dir)

#Folder-Liste anzeigen
print tree.GetPathFolders("D:\Python")

#File-Liste anzeigen
print tree.GetPathFiles("D:\Python")

#Umbenennen
tree.RenamePath("D:\Python", "C:\Python")

#Foldender Pfad existiert nicht mehr, da umbenannt
print tree.GetPathFolders("D:\Python")

#Nun geht es
print tree.GetPathFolders("C:\Python")
Über die Methoden SetFolderData und SetFileData könnte man dann noch jedem Objekt einen Datensatz zuordnen, evtl. auch über zusätzliche Methoden.

Edit (Leonidas): Code in Python Tags gesetzt, ist so lesbarer.
Gruß, Harry
Benutzeravatar
jens
Moderator
Beiträge: 8483
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Donnerstag 16. Dezember 2004, 14:20

Hmm... Naja, ich denke ich bleibe bei meiner Variante... Ich blick bei deiner nicht so ganz durch ;)
HarryH
User
Beiträge: 266
Registriert: Freitag 23. Mai 2003, 09:08
Wohnort: Deutschland

Donnerstag 16. Dezember 2004, 14:52

Meine Variante hat den Vorteil das ich fast direkt auf einen Pfad zugreifen kann. Ich muss nicht alle Elemente über Schleifen durchlaufen um die Daten zu einem File oder einem Ordner zu erhalten.
Darüber hinaus kann ich jedem "Pfad-Objekt" beliebige Daten zuordnen(dictionarys, listen ...).

Außerdem bin ich nicht nur an Filesystem-Strukturen gebunden. Ich kann auch andere Tree-Strukturen erzeugen, die keine Verbindung zum Filesystem besitzten. Deswegen kann man auch eine Liste oder eine Tuple als 'path' übergeben.
Gruß, Harry
Antworten