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.
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.
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:
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.
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.
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:
mode = 0o775 # übliche Oktalschreibweise
mode = 509 # Dezimalschreibweise
os.chmod(path, mode)
Um die Schreibweise rwx in eine Dezimalzahl umzuwandeln, kann folgende Funktion verwendet werden:
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.
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.
# 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:
content = ["Hund\n", "Katze\n", "Maus\n"]
with open(myfile, "w") as f:
f.writelines(content)
Datei lesen
► Python-Dokumentation: open read 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.
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.
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.
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:
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.
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.
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.
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.
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.
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:
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.
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.
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.
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.
dirname = os.environ['HOME'] + "/Python/temp"
os.rmdir(dirname)
# Alternative Methode, um einen nicht leeren Ordner zu löschen:
shutil.rmtree(dirname)