Bitte warten...

Python: Dateien und Ordner

Mit Python kann auf Dateien und Ordner des aktuellen Dateisystems sowohl lesend als auch schreibend zugegriffen werden. Welche Möglichkeiten es hier gibt und wie diese realisiert werden, soll in diesem Abschnitt beschrieben werden.

An dieser Stelle sei darauf hingewiesen, dass die Angaben zu Pfaden den unter unixoiden Betriebssystemen wie Linux gültigen Konventionen folgen. Ob Pfade beispielsweise unter Windows in gleicher Weise gebildet werden, entzieht sich meiner Kenntnis.

Für die folgenden Operationen werden die Module os bzw. shutil benötigt.

Arbeitsverzeichnis ermitteln und ändern

► Python-Dokumentation: getcwd() chdir()

Bei den Aktionen, die auf Dateien oder Ordner angewendet werden, ist zu beachten, dass die dort angegebenen Pfade relativ zum aktuellen Arbeitsverzeichnis verstanden werden, es sei denn, es sind absolute Pfade angegeben. Das aktuelle Arbeitsverzeichnis kann mit dem Befehl os.getcwd() (current working directory) ermittelt werden. Mit dem Befehl os.chdir() (change directory) kann es geändert werden.

Code kopieren
import os

print(os.getcwd())  # aktuelles Arbeitsverzeichnis anzeigen

os.chdir("myfolder")  # Arbeitsverzeichnis wechseln
print(os.getcwd())

Existenz einer Datei bzw. eines Ordners prüfen

► Python-Dokumentation: os.environ os.path.exists

Bevor auf eine Datei oder einen Ordner eine Aktion angewendet wird, wird man häufig zunächst feststellen wollen, ob dieses Objekt überhaupt existiert. Dazu wird die Funktion path.exists() aus dem Modul os verwendet. Diese Funktion findet auch Objekte, die einem anderen Besitzer gehören oder für die keine Zugriffsrechte bestehen.

Code kopieren
import os

path = os.environ['HOME']  # der aktuelle Benutzerordner
if os.path.exists(path) == True:
    print(path, "existiert.")
else:
    print(path, "existiert nicht.")

Objekttyp ermitteln

► Python-Dokumentation: os.path.isfile os.path.isdir os.path.islink

Möchte man wissen, ob es sich bei einem gefundenen Objekt um eine Datei, einen Ordner oder beispielsweise um einen Symlink handelt, kann man die Funktionen os.path.isfile(), os.path.isdir() sowie os.path.islink() verwenden:

Code kopieren
path = os.environ['HOME']  # der aktuelle Benutzerordner
if os.path.isdir(path) == True:
    print("Es ist ein Ordner.")
if os.path.isfile(path) == True:
    print("Es ist eine Datei.")
if os.path.islink(path) == True:
    print("Es ist ein Symlink.")

Objekteigenschaften ermitteln

► Python-Dokumentation: os.stat

Über die Funktion stat aus dem Modul os lassen sich diverse Eigenschaften von Ordnern bzw. Dateien ermitteln. Die Funktion gibt ein Tupel zurück, aus dem die Eigenschaften über den entsprechenden Index ausgelesen werden können.

Ebenso kann ein Wert über das zugehörige Schlüsselwort abgefragt werden.

Code kopieren
path = os.environ['HOME'] + "/Python/test"
props = os.stat(path)
print("Protection Bits:", props[0])
print("Inode-Nummer:", props[1])
print("Gerätenummer:", props[2])
print("Anzahl der Hardlinks:", props[3])
print("Benutzer-ID des Besitzers (uid):", props[4])
print("Gruppen-ID des Besitzers (gid):", props[5])
print("Größe des Objekts in Bytes:", props[6])
print("Zeitstempel des letzten Zugriffs auf das Objekt (atime):", props[7])
print("Zeitstempel der letzten Änderung des Objekts (mtime):", props[8])
print("Zeitstempel der letzten Änderung der Metadaten des Objekts (ctime):", props[9])

# Abfrage über Schlüsselwort:
print("st_mode:", os.stat(path).st_mode)

Zugriffsrechte ermitteln

► Python-Dokumentation: os.stat os.access

Dass ein Objekt existiert ist noch keine Garantie dafür, dass man auch Lese- oder Schreibzugriff darauf hat. Die bestehenden Zugriffsrechte können mit os.stat(path).st_mode ermittelt werden. Eine einfache Überprüfung des Lese- oder Schreibzugriffs kann mit der Funktion os.access() durchgeführt werden.

Code kopieren
mode = os.stat(path).st_mode
print("Mode: ", oct(mode))

if os.access(path, os.R_OK):
    print("Leserechte bestehen.")
else:
    print("Leserechte bestehen nicht.")
if os.access(path, os.W_OK):
    print("Schreibrechte bestehen.")
else:
    print("Schreibrechte bestehen nicht.")

Zugriffsrechte ändern

► Python-Dokumentation: os.chmod

Um die Zugriffsrechte eines Objekts zu ändern, wird die Methode os.chmod() verwendet. Der Modus kann in einem beliebigen Zahlensystem angegeben werden:

Code kopieren
mode = 0o775  # übliche Oktalschreibweise
mode = 509    # Dezimalschreibweise
os.chmod(path, mode)

Um die Schreibweise rwx in eine Dezimalzahl umzuwandeln, kann folgende Funktion verwendet werden:

Code kopieren
def rwx2dec(string):
    if len(string) != 9:
        return false
    else:
        val = 0
        for a in range(3):
            for p in range(3):
                if string[a * 3 + p] != "-":
                    val += (8 ** (2 - a)) * (2 ** (2 - p))
        return val

decmode = rwx2dec("rwxrwxr-x")
print(decmode)
print(oct(decmode))

Datei erzeugen oder leeren

► Python-Dokumentation: open

Um eine leere Datei zu erzeugen oder eine bestehende Datei zu leeren, genügt es, mit open() eine neues Dateiobjekt zu generieren und mit einer leeren Zeichenkette zu füllen. Dies setzt natürlich Schreibzugriff auf das Zielverzeichnis voraus.

Code kopieren
myfile = "test.txt"

# eine leere Datei erzeugen
with open(myfile, "w") as f:
    f.write("")

Datei schreiben

► Python-Dokumentation: open Reading and Writing Files

Mit der Funktion open() wird ein Dateiobjekt generiert, auf das lesend oder schreibend zugegriffen werden kann. Als erstes Argument wird der Pfad zur betreffenden Datei übergeben, als zweites Argument der Modus. Die Modi zum Schreiben sind:

"w": (write) Datei wird beim Öffnen geleert.
"a": (append) Datei wird um die in sie zu schreibenden Daten erweitert.

Anmerkung: Das Zeichen \n steht für einen Zeilenvorschub.

Code kopieren
# Text in eine Datei schreiben (bestehender Inhalt wird gelöscht)
with open(myfile, "w") as f:
    f.write("Wie geht's?")

# Text in eine Datei schreiben (bestehender Inhalt wird ergänzt)
with open(myfile, "a") as f:
    f.write("\nDanke, gut.")

► Python-Dokumentation: writelines

Mit der Funktion writelines() lassen sich beispielsweise die Elemente einer Liste zeilenweise in eine Datei schreiben, wobei der Zeilenvorschub explizit angegeben werden muss:

Code kopieren
content = ["Hund\n", "Katze\n", "Maus\n"]
with open(myfile, "w") as f:
    f.writelines(content)

Datei lesen

► Python-Dokumentation: open readline readlines Reading and Writing Files

Zum Lesen wird das Dateiobjekt mit dem Modus "r" geöffnet (kann auch weggelassen werden). Es stehen verschiedene Möglichkeiten zur Verfügung, den Inhalt einer Textdatei auszulesen:

Mit Hilfe von read() wird der gesamte Dateiinhalt in eine Variable gelesen. readline() ließt eine einzelne Zeile aus der Datei.

Die Funktion readlines() erzeugt eine Liste mit den Zeilen des Dateiinhalts als Elemente. Diese Elemente können dann in einer Schleife ausgelesen werden.

Es ist hierbei zu beachten, dass das Zeichen für den Zeilenvorschub \n am Ende einer Zeile Teil der Zeile ist und bei Bedarf entfernt werden muss. Im Beispiel erzeugt die Funktion print() ohnehin einen Zeilenvorschub.

Weiterhin ist zu beachten, dass zwischen dem Öffnen und dem Schließen eines Dateiobjekts der Inhalt nur ein Mal ausgelesen werden kann. Für ein erneutes Lesen muss das Dateiobjekt daher erst geschlossen und dann erneut geöffnet werden.

Code kopieren
nl = "\n"  # Zeilenvorschub

# Zunächst werden mehrere Zeilen in eine Datei geschrieben:
with open(myfile, "w") as f:
    f.write("Europa\nAsien\nAfrika\nAmerika\nAustralien")

# Jetzt werden die verschiedenen Methoden zum Lesen angewendet:
with open(myfile, "r") as f:
    content = f.read()
print(f"Gesamter Inhalt:\n{content}")

with open(myfile) as f:
    print(f"Erste Zeile:  {f.readline().strip(nl)}")
    print(f"Zweite Zeile: {f.readline().strip(nl)}")
    print(f"Dritte Zeile: {f.readline().strip(nl)}")

with open(myfile) as f:
    content = f.readlines()
z = 1
for line in content:
    print(f"Zeile {z}: {line.strip(nl)}")
    z += 1

Mit der Direktive r+ (lesen und schreiben) kann der Inhalt einer Datei überschrieben werden, ohne dass der ursprüngliche Inhalt gelöscht wird.

Code kopieren
with open(myfile, "w") as f:
    f.write("Europa\nAsien\nAfrika\nAmerika\nAustralien")

with open(myfile, "r+") as f:
    f.write("Asien\nEuropa")  # tauscht die ersten beiden Zeilen aus

Datei an konkreter Position schreiben bzw. lesen

► Python-Dokumentation: Reading and Writing Files

Mit der Funktion seek() lässt sich ein Zeiger auf eine bestimmte Position innerhalb einer Datei setzen, an der diese Datei geschrieben bzw. gelesen werden kann.

Code kopieren
with open(myfile, "w") as f:
    f.write("Hund  Katze Maus\n")
    f.write("Fisch Pferd Wal\n")
    f.write("Affe  Biene Schmetterling")

with open(myfile, "r+") as f:  # Öffnet eine Datei zum Lesen und Schreiben
    f.seek(23)  # Setzt den Zeiger an die Position 23
    content = f.read(5)  # Liest 5 Zeichen ab der Zeigerposition
    print(content)
    f.seek(23)
    f.write("Ziege")  # Schreibt den String an die Zeigerposition
    f.seek(0)
    content = f.read()
    print(content)

Auf diese Weise lässt sich auch Text oberhalb des ursprünglichen Inhalts ergänzen:

Code kopieren
with open(myfile, "w") as f:
    f.write("Europa\nAsien\nAfrika\nAmerika\nAustralien")

with open(myfile, "r+") as f:
    c = f.read()
    f.seek(0)
    f.write("Antarktika\n" + c)

Datei umbenennen/verschieben

► Python-Dokumentation: os.rename os.renames

Mit os.rename() lässt sich eine existierende Datei umbenennen bzw. verschieben. Weichen die Elternordner des Zielpfades von dem des Quellpfades ab (d. h., die Datei wird nicht umbenannt, sondern verschoben) und existiert mindestens ein Ordner des Zielpfades nicht, so führt dies zu einem OSError. In diesem Fall kann os.renames() verwendet werden, um nicht existierende Ordner im Zielpfad zu erzeugen.

Falls unter dem Zielpfad bereits eine Datei gleichen Namens existiert, so wird diese stillschweigend überschrieben. Existiert bereits ein Ordner mit dem Namen des Zielpfades, so führt dies zu einem OSError.

Siehe auch os.replace und shutil.move.

Code kopieren
source = os.environ['HOME'] + "/Python/testdatei"
target = os.environ['HOME'] + "/Python/testdatei2"
os.rename(source, target)

target = os.environ['HOME'] + "/Python/temp/testdatei2"
os.rename(source, target)  # Existiert der Zielpfad nicht, so führt dies zu einem OSError.

# Statt dessen kann os.renames verwendet werden:
os.renames(source, target)

Datei kopieren

► Python-Dokumentation: shutil.copy shutil.copy2

Um eine Datei an einen anderen Ort zu kopieren, kann man die Methode copy aus dem Modul shutil verwenden. Falls man Wert darauf legt, dass die Metadaten der Datei erhalten bleiben (wie beispielsweise der Zeitpunkt, an dem die Datei erzeugt bzw. zuletzt geändert wurde), so muss man die Methode copy2 verwenden.

Sollte mindestens ein Ordner des Zielpfades nicht existieren, so führt dies zu einem IOError.

Siehe auch shutil.copyfile.

Code kopieren
source = os.environ['HOME'] + "/Python/testdatei"
target = os.environ['HOME'] + "/Python/testdatei2"
shutil.copy(source, target)

target = os.environ['HOME'] + "/Python/testdatei3"
shutil.copy2(source, target)

Datei löschen

► Python-Dokumentation: os.remove os.unlink

Um eine Datei zu löschen, verwendet man die Methode remove aus dem Modul os. Dies ist identisch mit der Methode os.unlink.

Code kopieren
filename = os.environ['HOME'] + "/Python/testdatei3"
os.remove(filename)

Ordner anlegen

► Python-Dokumentation: os.mkdir os.makedirs

Um einen neuen Ordner anzulegen, verwendet man die Methode mkdir aus dem Modul os. Sollte mindestens ein Ordner des Zielpfades nicht existieren, so führt dies zu einem OSError. In diesem Fall verwendet man die Methode os.makedirs, um fehlende Ordner ebenfalls anzulegen.

Sollte der gewünschte Ordner bereits existieren, so führt dies ebenfalls zu einem OSError.

Code kopieren
dirname = os.environ['HOME'] + "/Python/temp"
os.mkdir(dirname)

dirname = os.environ['HOME'] + "/Python/temp2/myfolder"
os.makedirs(dirname)

Ordnerinhalt auslesen

► Python-Dokumentation: os.listdir

Um den Inhalt eines Ordners auszulesen, verwendet man die Methode listdir aus dem Modul os. Die Reihenfolge der zurückgegebenen Objektnamen ist beliebig, weshalb es unter Umständen empfehlenswert sein kann, die zurückgegebene Liste zunächst mit sort() zu sortieren.

Code kopieren
dirname = os.environ['HOME'] + "/Python"
objects = os.listdir(dirname)
objects.sort()
for objectname in objects:
    print(objectname)

Möchte man den Ordnerinhalt nur nach bestimmten enthaltenen Objekten (Dateien, Ordner oder Symlinks) auslesen, so kann man sich mit folgender Funktion behelfen:

Code kopieren
def folder_objects(dirname, otype = "all"):
    if (os.path.exists(dirname) == False or
        os.path.isdir(dirname) == False or
        os.access(dirname, os.R_OK) == False):
        return False
    else:
        objects = os.listdir(dirname)
        result = []
        for objectname in objects:
            objectpath = dirname + "/" + objectname
            if (otype == "all" or
                (otype == "dir"  and os.path.isdir(objectpath)  == True) or
                (otype == "file" and os.path.isfile(objectpath) == True) or
                (otype == "link" and os.path.islink(objectpath) == True)):
                result.append(objectname)
        result.sort()
        return result

dirname = os.environ['HOME'] + "/Python"
print("Alle:    ", folder_objects(dirname))
print("Ordner:  ", folder_objects(dirname, "dir"))
print("Dateien: ", folder_objects(dirname, "file"))
print("Symlinks:", folder_objects(dirname, "link"))

Eine alternative Methode zum Auslesen eines Ordners bietet die Funktion glob aus dem gleichnamigen Modul.

Code kopieren
import os, glob

dirname = os.environ['HOME'] + "/Python"
objects = glob.glob(dirname + "/*")
objects.sort()
for objectname in objects:
    print(objectname)

Ordner umbenennen/verschieben

► Python-Dokumentation: os.rename os.renames

Mit os.rename() lässt sich ein existierender Ordner umbenennen bzw. verschieben. Weichen die Elternordner des Zielpfades von dem des Quellpfades ab (d. h., der Ordner wird nicht umbenannt, sondern verschoben) und existiert mindestens ein Ordner des Zielpfades nicht, so führt dies zu einem OSError. In diesem Fall kann os.renames() verwendet werden, um nicht existierende Ordner im Zielpfad zu erzeugen.

Falls unter dem Zielpfad bereits ein Ordner gleichen Namens existiert, so wird dieser stillschweigend überschrieben, sofern dieser leer ist. Ansonsten führt der Versuch zu einem OSError. Existiert bereits eine Datei mit dem Namen des Zielpfades, so führt dies ebenfalls zu einem OSError.

Siehe auch os.replace und shutil.move.

Code kopieren
source = os.environ['HOME'] + "/Python/temp"
target = os.environ['HOME'] + "/Python/temp2"
os.rename(source, target)

source = target
target = os.environ['HOME'] + "/Python/temp3/test"
os.rename(source, target)  # Existiert der Zielpfad nicht, so führt dies zu einem OSError.

# Statt dessen kann os.renames verwendet werden:
os.renames(source, target)

Ordner kopieren

► Python-Dokumentation: shutil.copytree

Um einen Ordner mit allen enthaltenen Objekten an einen anderen Ort zu kopieren, wird die Methode copytree aus dem Modul shutil verwendet. Nicht vorhandene Ordner des Zielpfades werden hierbei automatisch erzeugt. Existiert bereits eine Datei oder ein Ordner mit dem Namen des Zielpfades, so führt dies zu einem OSError.

Die Metadaten der enthaltenen Ordner und Dateien werden beibehalten. Sollen die Metadaten der enthaltenen Dateien neu geschrieben werden, so übergibt man zusätzlich das Argument copy_function=shutil.copy.

Code kopieren
source = os.environ['HOME'] + "/Python/temp"
target = os.environ['HOME'] + "/Python/temp2"
shutil.copytree(source, target)

# Alternative Methode, bei der die Metadaten der enthaltenen Dateien neu geschrieben werden:
shutil.copytree(source, target, copy_function=shutil.copy)

Ordner löschen

► Python-Dokumentation: os.rmdir shutil.rmtree

Um einen leeren Ordner zu löschen, verwendet man die Methode rmdir aus dem Modul os. Der Versuch, einen nicht leeren Ordner mit dieser Methode zu löschen, führt zu einem OSError.

Um einen Ordner mit allen enthaltenen Objekten zu löschen, verwendet man die Methode rmtree aus dem Modul shutil.

Code kopieren
dirname = os.environ['HOME'] + "/Python/temp"
os.rmdir(dirname)

# Alternative Methode, um einen nicht leeren Ordner zu löschen:
shutil.rmtree(dirname)