Vom Übersetzer: Hallo Habr! Ich präsentiere Ihnen die Übersetzung des Artikels Warum Sie Pathlib verwenden sollten und seine Fortsetzung: Nein, Pathlib ist wirklich großartig . Neue Python-Funktionen wie asyncio, der Operator: = und die optionale Eingabe werden jetzt besonders berücksichtigt. Gleichzeitig ist das Risiko für ein Radar nicht so bedeutend (obwohl :: eine ernsthafte Innovation als Sprache bezeichnet, die sich nicht als ernsthafte Innovation herausstellt), sondern sehr nützliche Innovationen in einer Sprache. Insbesondere bei einer Reihe von Artikeln, die einem Thema gewidmet waren, fand ich sie nicht (mit Ausnahme eines Absatzes hier ), weshalb ich mich entschied, die Situation zu korrigieren.
Als ich vor einigen Jahren das damals neue Pathlib- Modul entdeckte, entschied ich aus tiefstem Kopf, dass es sich nur um eine etwas umständliche objektorientierte Version des os.path
Moduls handelt. Ich habe mich geirrt pathlib
ist wirklich wunderbar !
In diesem Artikel werde ich versuchen, mich in pathlib
zu pathlib
. Ich hoffe, dieser Artikel pathlib
Sie dazu , pathlib
in jeder Situation zu verwenden, in pathlib
Sie mit Dateien in Python arbeiten .
Teil 1.
os.path
umständlich
Das Modul os.path
immer das, was wir für Python-Pfade verwendet haben. Im Prinzip gibt es alles, was Sie brauchen, aber oft sieht es nicht zu elegant aus.
Soll ich es so importieren?
import os.path BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) TEMPLATES_DIR = os.path.join(BASE_DIR, 'templates')
Oder so?
from os.path import abspath, dirname, join BASE_DIR = dirname(dirname(abspath(__file__))) TEMPLATES_DIR = join(BASE_DIR, 'templates')
Vielleicht hat die join
Funktion einen zu allgemeinen Namen, und wir sollten so etwas tun:
from os.path import abspath, dirname, join as joinpath BASE_DIR = dirname(dirname(abspath(__file__))) TEMPLATES_DIR = joinpath(BASE_DIR, 'templates')
Alle oben genannten Optionen scheinen mir nicht allzu bequem zu sein. Wir übergeben Zeichenfolgen an Funktionen, die Zeichenfolgen zurückgeben, die wir an die nächsten Funktionen übergeben, die mit Zeichenfolgen arbeiten. Es ist einfach so passiert, dass sie alle Pfade enthalten, aber sie sind immer noch nur Linien.
Die Verwendung von Zeichenfolgen für die Eingabe und Ausgabe in os.path
Funktionen os.path
sehr unpraktisch, da Sie den Code von innen nach außen lesen müssen. Ich möchte diese Aufrufe von verschachtelt in sequentiell konvertieren. Das können Sie mit pathlib
tun!
from pathlib import Path BASE_DIR = Path(__file__).resolve().parent.parent TEMPLATES_DIR = BASE_DIR.joinpath('templates')
Das Modul os.path
erfordert verschachtelte Funktionsaufrufe. Mit pathlib
können wir jedoch Ketten aufeinanderfolgender Aufrufe von Methoden und Attributen der Path
Klasse mit einem entsprechenden Ergebnis erstellen .
Ich weiß, was Sie denken: Stoppen Sie, diese Path
sind nicht die gleichen wie zuvor, wir arbeiten nicht mehr auf Pfadlinien! Wir werden später auf dieses Thema zurückkommen (Hinweis: In fast jeder Situation sind diese beiden Ansätze austauschbar).
os
überladen
Das klassische os.path
Modul wurde für die Arbeit mit Pfaden entwickelt. Nachdem Sie jedoch etwas mit dem Pfad tun möchten (z. B. ein Verzeichnis erstellen), müssen Sie auf ein anderes Modul zugreifen, häufig os
.
os
enthält eine Reihe von Dienstprogrammen für die Arbeit mit Dateien und Verzeichnissen: mkdir
, getcwd
, chmod
, stat
, remove
, getcwd
, rmdir
. Auch chdir
, link
, walk
, listdir
, makedirs
, renames
, removedirs
, unlink
, symlink
. Und eine ganze Reihe von getenv
, die putenv
nichts mit Dateisystemen zu getenv
: fork
, getenv
, putenv
, getlogin
, getlogin
, system
, ... Ein paar Dutzend weitere Dinge, die ich hier nicht erwähnen werde.
Das os
ist für eine Vielzahl von Aufgaben konzipiert. Dies ist eine solche Box mit allem, was mit dem Betriebssystem zu tun hat. Es gibt viele nützliche Funktionen in os
, aber die Navigation ist nicht immer einfach: Oft müssen Sie sich ein wenig mit dem Modul befassen, bevor Sie das finden, was Sie benötigen.
pathlib
überträgt die meisten Dateisystemfunktionen auf pathlib
.
Hier ist der Code, der das src/__pypackages__
und unsere .editorconfig
Datei in src/.editorconfig
:
import os import os.path os.makedirs(os.path.join('src', '__pypackages__'), exist_ok=True) os.rename('.editorconfig', os.path.join('src', '.editorconfig'))
Hier ist ähnlicher Code mit Path
from pathlib import Path Path('src/__pypackages__').mkdir(parents=True, exist_ok=True) Path('.editorconfig').rename('src/.editorconfig')
Beachten Sie, dass das zweite Codebeispiel viel einfacher zu lesen ist, da es von links nach rechts organisiert ist - dies alles dank der Methodenketten.
glob
nicht vergessen
Nicht nur os
und os.path
enthalten Methoden, die sich auf das Dateisystem beziehen. Erwähnenswert ist auch glob
, der nicht als nutzlos bezeichnet werden kann.
Wir können die Funktion glob.glob
verwenden, um nach Dateien nach einem bestimmten Muster zu suchen:
from glob import glob top_level_csv_files = glob('*.csv') all_csv_files = glob('**/*.csv', recursive=True)
Das pathlib
Modul bietet auch ähnliche Methoden:
from pathlib import Path top_level_csv_files = Path.cwd().glob('*.csv') all_csv_files = Path.cwd().rglob('*.csv')
Nach dem Wechsel zum pathlib
Modul verschwindet die Notwendigkeit für das glob
vollständig : Alles, was Sie benötigen, ist bereits ein integraler Bestandteil von Path
Objekten
pathlib
macht einfache dinge noch einfacher
pathlib
vereinfacht viele schwierige Situationen, macht aber auch einige einfache Codefragmente noch einfacher .
Möchten Sie den gesamten Text in einer oder mehreren Dateien lesen?
Sie können die Datei öffnen, den Inhalt lesen und die Datei mit dem with
Block schließen:
from glob import glob file_contents = [] for filename in glob('**/*.py', recursive=True): with open(filename) as python_file: file_contents.append(python_file.read())
Sie können auch die Methode read_text
für read_text
verwenden und Listen generieren, um dasselbe Ergebnis in einem Ausdruck zu erhalten:
from pathlib import Path file_contents = [ path.read_text() for path in Path.cwd().rglob('*.py') ]
Aber was ist, wenn Sie in eine Datei schreiben müssen?
So sieht es mit open
:
with open('.editorconfig') as config: config.write('# config goes here')
Oder Sie können die Methode write_text
verwenden:
Path('.editorconfig').write_text('# config goes here')
Wenn Sie open
aus irgendeinem Grund entweder als Kontextmanager oder für persönliche Einstellungen verwenden müssen, bietet Path
die open
Methode als Alternative:
from pathlib import Path path = Path('.editorconfig') with path.open(mode='wt') as config: config.write('# config goes here')
Ab Python 3.6 können Sie Ihren Path
direkt zum open
:
from pathlib import Path path = Path('.editorconfig') with open(path, mode='wt') as config: config.write('# config goes here')
Pfadobjekte machen Ihren Code offensichtlicher
Was zeigen die folgenden Variablen an? Was bedeuten ihre Bedeutungen?
person = '{"name": "Trey Hunner", "location": "San Diego"}' pycon_2019 = "2019-05-01" home_directory = '/home/trey'
Jede Variable zeigt auf eine Linie. Aber jeder von ihnen hat unterschiedliche Bedeutungen: Der erste ist JSON, der zweite ist das Datum und der dritte ist der Dateipfad.
Diese Darstellung von Objekten ist etwas nützlicher:
from datetime import date from pathlib import Path person = {"name": "Trey Hunner", "location": "San Diego"} pycon_2019 = date(2019, 5, 1) home_directory = Path('/home/trey')
JSON-Objekte können in ein Wörterbuch deserialisiert werden, Datumsangaben können nativ mit datetime.date
werden und Dateipfadobjekte können als Path
Durch die Verwendung von Path
wird Ihr Code expliziter. Wenn Sie mit Datumsangaben arbeiten möchten, verwenden Sie date
. Wenn Sie mit Dateipfaden arbeiten möchten, verwenden Sie Path
.
Ich bin kein sehr großer Unterstützer von OOP. Klassen fügen eine zusätzliche Abstraktionsebene hinzu, und Abstraktionen erschweren manchmal das System, anstatt es zu vereinfachen. Gleichzeitig glaube ich, dass pathlib.Path
eine nützliche Abstraktion ist . Ziemlich schnell wird es eine akzeptierte Entscheidung.
Dank PEP 519 werden Path
zum Standard für die Arbeit mit Pfaden. Zum Zeitpunkt von Python 3.6 shutil
os.path
os
, shutil
und os.path
ordnungsgemäß mit diesen Objekten. Sie können pathlib
zu pathlib
wechseln, transparent für Ihre Codebasis!
Was fehlt in pathlib
?
pathlib
cool, aber nicht umfassend. Es gibt definitiv mehrere Möglichkeiten, die ich in das Modul aufnehmen möchte .
Das erste, was mir in den Sinn kommt, ist das Fehlen von shutil
, die shutil
. Obwohl Sie Path
als shutil
Parameter zum Kopieren / Löschen / Verschieben von Dateien und Verzeichnissen übergeben können, können Sie sie nicht als Methoden für Path
Objekte aufrufen.
Um Dateien zu kopieren, müssen Sie Folgendes tun:
from pathlib import Path from shutil import copyfile source = Path('old_file.txt') destination = Path('new_file.txt') copyfile(source, destination)
Es gibt auch kein Analogon zur os.chdir
Methode. Dies bedeutet, dass Sie es importieren müssen, wenn Sie das aktuelle Verzeichnis ändern müssen:
from pathlib import Path from os import chdir parent = Path('..') chdir(parent)
Es gibt auch kein Äquivalent zur Funktion os.walk
. Obwohl Sie Ihre eigene Funktion im Geiste eines walk
ohne allzu große Schwierigkeiten schreiben können.
Ich hoffe, dass eines Tages pathlib.Path
Objekte Methoden für einige der genannten Operationen enthalten werden. Aber selbst in diesem Szenario finde ich es viel einfacher, pathlib
mit etwas anderem zu verwenden, als os.path
und alles andere .
Ist es immer notwendig, pathlib
zu verwenden?
Ab Python 3.6 funktionieren Pfade fast überall dort, wo Sie Zeichenfolgen verwenden . Daher sehe ich keinen Grund , pathlib
nicht zu verwenden, wenn Sie Python 3.6 und höher verwenden.
Wenn Sie eine frühere Version von Python 3 verwenden, können Sie das Path
Objekt jederzeit in einen str
Aufruf str
, um eine Zeichenfolge str
, wenn Sie in das Land der Zeilen zurückkehren müssen. Das ist nicht zu elegant, aber es funktioniert:
from os import chdir from pathlib import Path chdir(Path('/home/trey'))
Teil 2. Antworten auf Fragen.
Nachdem der erste Teil veröffentlicht worden war, hatten einige Leute einige Fragen. Jemand sagte, ich pathlib
os.path
und pathlib
unehrlich verglichen. Einige sagten, dass die Verwendung von os.path
in der Python-Community so tief verwurzelt os.path
, dass das Wechseln zu einer neuen Bibliothek sehr lange dauern wird. Ich habe auch einige Fragen zur Leistung gesehen.
In diesem Teil möchte ich diese Themen kommentieren. Dies kann sowohl als pathlib
Schutz als auch als Liebesbrief an PEP 519 angesehen werden .
Vergleichen Sie os.path
und pathlib
, um ehrlich zu sein
Im letzten Teil habe ich die folgenden zwei Codefragmente verglichen:
import os import os.path os.makedirs(os.path.join('src', '__pypackages__'), exist_ok=True) os.rename('.editorconfig', os.path.join('src', '.editorconfig'))
from pathlib import Path Path('src/__pypackages__').mkdir(parents=True, exist_ok=True) Path('.editorconfig').rename('src/.editorconfig')
Dies scheint ein unfairer Vergleich zu sein, da die Verwendung von os.path.join
im ersten Beispiel sicherstellt, dass auf allen Plattformen die richtigen Trennzeichen verwendet werden, was ich im zweiten Beispiel nicht getan habe. Tatsächlich ist alles in Ordnung, da Path Pfadtrennzeichen automatisch normalisiert
Wir können dies beweisen, indem wir das Path
Objekt unter Windows in eine Zeichenfolge konvertieren:
>>> str(Path('src/__pypackages__')) 'src\\__pypackages__'
Es macht keinen Unterschied, ob wir die joinpath
Methode, das '/'
in der joinpath
, den /
-Operator (eine weitere nette Funktion von Path
) verwenden oder einzelne Argumente an den Path-Konstruktor übergeben. Wir erhalten das gleiche Ergebnis:
>>> Path('src', '.editorconfig') WindowsPath('src/.editorconfig') >>> Path('src') / '.editorconfig' WindowsPath('src/.editorconfig') >>> Path('src').joinpath('.editorconfig') WindowsPath('src/.editorconfig') >>> Path('src/.editorconfig') WindowsPath('src/.editorconfig')
Das letzte Beispiel verursachte einige Verwirrung bei Leuten, die pathlib
, pathlib
nicht klug genug, um /
durch \
in der pathlib
zu ersetzen. Zum Glück ist alles in Ordnung!
Mit Path
müssen Sie sich nicht mehr um die Richtung der Schrägstriche kümmern: Definieren Sie alle Ihre Pfade mit /
, und das Ergebnis ist für jede Plattform vorhersehbar.
Sie müssen sich nicht um die Normalisierung der Pfade kümmern.
Wenn Sie Linux oder Mac ausführen, ist es sehr einfach, Ihrem Code versehentlich Fehler hinzuzufügen, die nur Windows-Benutzer betreffen. Wenn Sie die Verwendung von os.path.join
und \ oder os.path.normcase
zum Konvertieren von Schrägstrichen in für die aktuelle Plattform geeignete Schrägstriche nicht genau überwachen, können Sie Code schreiben, der unter Windows nicht ordnungsgemäß funktioniert .
Hier ist ein Beispiel für einen Windows-spezifischen Fehler:
import sys import os.path directory = '.' if not sys.argv[1:] else sys.argv[1] new_file = os.path.join(directory, 'new_package/__init__.py')
Darüber hinaus funktioniert ein solcher Code überall korrekt:
import sys from pathlib import Path directory = '.' if not sys.argv[1:] else sys.argv[1] new_file = Path(directory, 'new_package/__init__.py')
Zuvor war der Programmierer für die Verkettung und Normalisierung von Pfaden verantwortlich, genau wie in Python 2 war der Programmierer für die Entscheidung verantwortlich, wo Unicode anstelle von Bytes verwendet werden soll. Dies ist nicht mehr Ihre Aufgabe - Path
löst alle diese Probleme für Sie.
Ich verwende kein Windows und habe keinen Windows-Computer. Aber sehr viele Leute, die meinen Code verwenden, werden sehr wahrscheinlich Windows verwenden, und ich möchte, dass alles für sie richtig funktioniert.
Wenn die Möglichkeit besteht, dass Ihr Code unter Windows ausgeführt wird, sollten Sie ernsthaft in Betracht ziehen, auf pathlib
.
Machen Sie sich keine Sorgen um die Normalisierung : Verwenden Sie Path
trotzdem, wenn es um Dateipfade geht.
Klingt cool, aber ich habe eine Drittanbieter-Bibliothek, die kein pathlib
!
Sie haben eine große Codebasis, die mit Zeichenfolgen als Pfaden arbeitet. Warum zu pathlib
wechseln, wenn das bedeutet, dass alles neu geschrieben werden muss?
Stellen wir uns vor, Sie haben folgende Funktion:
import os import os.path def make_editorconfig(dir_path): """Create .editorconfig file in given directory and return filename.""" filename = os.path.join(dir_path, '.editorconfig') if not os.path.exists(filename): os.makedirs(dir_path, exist_ok=True) open(filename, mode='wt').write('') return filename
Die Funktion nimmt ein Verzeichnis und erstellt dort eine .editorconfig
Datei, .editorconfig
so:
>>> import os.path >>> make_editorconfig(os.path.join('src', 'my_package')) 'src/my_package/.editorconfig'
Wenn Sie die Zeilen durch Path
ersetzen, funktioniert auch alles:
>>> from pathlib import Path >>> make_editorconfig(Path('src/my_package')) 'src/my_package/.editorconfig'
Aber wie?
os.path.join
akzeptiert os.path.join
(seit Python 3.6). Gleiches gilt für os.makedirs
.
Tatsächlich akzeptiert die integrierte open
Funktion Path
, shutil
akzeptiert Path
und alles in der Standardbibliothek, das zum Akzeptieren von Strings verwendet wird, sollte jetzt sowohl mit Path
als auch mit Strings funktionieren.
Wir sollten PEP 519 dafür danken, das die abstrakte Klasse os.PathLike
und ankündigte, dass alle integrierten Dienstprogramme für die Arbeit mit Dateipfaden jetzt sowohl mit Zeichenfolgen als auch mit Path
funktionieren sollten.
Aber meine Lieblingsbibliothek hat Path, besser als der Standard!
Möglicherweise verwenden Sie bereits eine Bibliothek eines Drittanbieters, die die Path
bereitstellt, die sich von der Standardbibliothek unterscheidet. Vielleicht magst du sie mehr.
Zum Beispiel enthalten django-environ , path.py , plumbum und visidata jeweils ihre eigenen Path
Objekte. Einige dieser Bibliotheken sind älter als pathlib
und haben beschlossen, von str
zu erben, damit sie an Funktionen übergeben werden können, die Strings als Pfade erwarten. Dank PEP 519 ist die Integration von Bibliotheken von Drittanbietern in Ihren Code einfacher und ohne die Notwendigkeit einer Vererbung von str
.
Stellen wir uns vor, Sie möchten pathlib
nicht verwenden, da Path
unveränderliche Objekte sind und Sie ihren Status wirklich wirklich ändern möchten. Mit PEP 519 können Sie Ihre beste veränderbare Version von Path
erstellen. Implementieren Sie dazu einfach die Methode __fspath__
Jede selbstgeschriebene Implementierung von Path
kann jetzt nativ mit in Python integrierten Funktionen arbeiten, die Dateipfade erwarten. Auch wenn Sie pathlib
nicht mögen, ist die Tatsache, dass es existiert, ein großes Plus für Bibliotheken von Drittanbietern mit eigenem Path
Aber pathlib.Path
und str
mischen sich nicht, oder?
Sie denken wahrscheinlich: Das ist natürlich alles großartig, aber wird dieser Ansatz mit manchmal Zeilen und manchmal Pfaden meinem Code etwas Komplexität verleihen?
Die Antwort auf diese Frage lautet bis zu einem gewissen Grad ja. Dieses Problem hat jedoch eine ziemlich einfache Problemumgehung.
PEP 519 hat neben PathLike
noch einige weitere Dinge PathLike
: Erstens können Sie PathLike
in eine Zeichenfolge konvertieren, und zweitens können Sie PathLike
in einen Path
PathLike
.
Nehmen wir zwei Objekte - einen String und einen Path
(oder was auch immer mit der fspath- Methode):
from pathlib import Path import os.path p1 = os.path.join('src', 'my_package') p2 = Path('src/my_package')
Die Funktion os.fspath
normalisiert beide Objekte und os.fspath
sie in Zeichenfolgen um:
>>> from os import fspath >>> fspath(p1), fspath(p2) ('src/my_package', 'src/my_package')
In diesem Fall kann Path
beide Objekte in einen Konstruktor aufnehmen und in Path
konvertieren:
>>> Path(p1), Path(p2) (PosixPath('src/my_package'), PosixPath('src/my_package'))
Dies bedeutet, dass Sie das Ergebnis von make_editorconfig
bei make_editorconfig
wieder in Path
konvertieren können:
>>> from pathlib import Path >>> Path(make_editorconfig(Path('src/my_package'))) PosixPath('src/my_package/.editorconfig')
Die beste Lösung wäre natürlich, make_editorconfig
mit pathlib
neu zu schreiben.
pathlib
zu langsam
Ich habe mehrmals über pathlib
Leistung von pathlib
. Es ist wahr - pathlib
kann langsam sein. Das Erstellen von Tausenden von Path
kann das Programmverhalten erheblich beeinflussen.
Ich habe beschlossen, die Leistung von pathlib
und os.path
auf meinem Computer mit zwei verschiedenen Programmen zu messen, die nach allen .py
Dateien im aktuellen Verzeichnis suchen
Hier ist die Version von os.walk
:
from os import getcwd, walk extension = '.py' count = 0 for root, directories, filenames in walk(getcwd()): for filename in filenames: if filename.endswith(extension): count += 1 print(f"{count} Python files found")
Und hier ist die Version mit Path.rglob
:
from pathlib import Path extension = '.py' count = 0 for filename in Path.cwd().rglob(f'*{extension}'): count += 1 print(f"{count} Python files found")
Das Testen der Leistung von Programmen, die mit dem Dateisystem arbeiten, ist eine schwierige Aufgabe, da sich die Betriebszeit erheblich ändern kann. Ich habe beschlossen, jedes Skript zehnmal auszuführen und die besten Ergebnisse für jedes Programm zu vergleichen.
Beide Programme haben 97507 Dateien in dem Verzeichnis gefunden, in dem ich sie ausgeführt habe. Der erste arbeitete in 1,914 Sekunden, der zweite in 3,430 Sekunden.
Wenn ich den Parameter extension=''
setze, finden diese Programme ungefähr 600.000 Dateien, und der Unterschied nimmt zu. Das erste Programm arbeitete in 1,888 Sekunden und das zweite in 7,485 Sekunden.
Daher ist pathlib
für Dateien mit der Erweiterung .py
etwa doppelt so langsam und beim pathlib
in meinem Home-Verzeichnis viermal langsamer . Die relative Leistungslücke zwischen pathlib
und pathlib
ist pathlib
.
In meinem Fall ändert sich diese Geschwindigkeit nicht viel. Ich habe alle Dateien in meinem Verzeichnis durchsucht und 6 Sekunden verloren. Wenn ich die Aufgabe hätte, 10 Millionen Dateien zu verarbeiten, würde ich sie höchstwahrscheinlich neu schreiben. Aber während es keine solche Notwendigkeit gibt, können Sie warten.
Wenn Sie einen heißen Code haben und pathlib
den Betrieb offensichtlich negativ beeinflusst, ist es nichts Falsches, ihn durch eine Alternative zu ersetzen. Sie sollten den Code nicht optimieren, was kein Engpass ist - dies ist eine zusätzliche Zeitverschwendung, die normalerweise auch zu schlecht lesbarem Code ohne viel Auspuff führt.
Verbesserung der Lesbarkeit
Ich möchte diesen Gedankenstrom mit einigen Refactoring-Beispielen unter Verwendung von pathlib
. Ich habe ein paar kleine Beispiele für Code genommen, der mit Dateien funktioniert, und sie mit pathlib
arbeiten pathlib
. Ich werde den größten Teil des Codes ohne Kommentar zu Ihrem Gericht hinterlassen - entscheiden Sie, welche Version Ihnen am besten gefällt.
Hier ist die Funktion make_editorconfig
, die wir zuvor gesehen haben:
import os import os.path def make_editorconfig(dir_path): """Create .editorconfig file in given directory and return filename.""" filename = os.path.join(dir_path, '.editorconfig') if not os.path.exists(filename): os.makedirs(dir_path, exist_ok=True) open(filename, mode='wt').write('') return filename
Und hier ist die in pathlib
umgeschriebene pathlib
:
from pathlib import Path def make_editorconfig(dir_path): """Create .editorconfig file in given directory and return filepath.""" path = Path(dir_path, '.editorconfig') if not path.exists(): path.parent.mkdir(exist_ok=True, parent=True) path.touch() return path
Hier ist ein Konsolenprogramm, das eine Zeile mit einem Verzeichnis erstellt und den Inhalt einer .gitignore
Datei .gitignore
, falls vorhanden:
import os.path import sys directory = sys.argv[1] ignore_filename = os.path.join(directory, '.gitignore') if os.path.isfile(ignore_filename): with open(ignore_filename, mode='rt') as ignore_file: print(ignore_file.read(), end='')
Gleiches gilt für pathlib
:
from pathlib import Path import sys directory = Path(sys.argv[1]) ignore_path = directory / '.gitignore' if ignore_path.is_file(): print(ignore_path.read_text(), end='')
Hier ist ein Programm, das alle doppelten Dateien im aktuellen Ordner und in den Unterordnern druckt:
from collections import defaultdict from hashlib import md5 from os import getcwd, walk import os.path def find_files(filepath): for root, directories, filenames in walk(filepath): for filename in filenames: yield os.path.join(root, filename) file_hashes = defaultdict(list) for path in find_files(getcwd()): with open(path, mode='rb') as my_file: file_hash = md5(my_file.read()).hexdigest() file_hashes[file_hash].append(path) for paths in file_hashes.values(): if len(paths) > 1: print("Duplicate files found:") print(*paths, sep='\n')
Gleiches gilt für c pathlib
:
from collections import defaultdict from hashlib import md5 from pathlib import Path def find_files(filepath): for path in Path(filepath).rglob('*'): if path.is_file(): yield path file_hashes = defaultdict(list) for path in find_files(Path.cwd()): file_hash = md5(path.read_bytes()).hexdigest() file_hashes[file_hash].append(path) for paths in file_hashes.values(): if len(paths) > 1: print("Duplicate files found:") print(*paths, sep='\n')
, , -, . pathlib
.
pathlib.Path
.
/
pathlib.Path
. , .
>>> path1 = Path('dir', 'file') >>> path2 = Path('dir') / 'file' >>> path3 = Path('dir/file') >>> path3 WindowsPath('dir/file') >>> path1 == path2 == path3 True
Python (. open
) Path
, , pathlib
, !
from shutil import move def rename_and_redirect(old_filename, new_filename): move(old, new) with open(old, mode='wt') as f: f.write(f'This file has moved to {new}')
>>> from pathlib import Path >>> old, new = Path('old.txt'), Path('new.txt') >>> rename_and_redirect(old, new) >>> old.read_text() 'This file has moved to new.txt'
pathlib
, , PathLike
. , , , PEP 519 .
>>> from plumbum import Path >>> my_path = Path('old.txt') >>> with open(my_path) as f: ... print(f.read()) ... This file has moved to new.txt
pathlib
, ( , ), , .
, pathlib
. Python :
from pathlib import Path gitignore = Path('.gitignore') if gitignore.is_file(): print(gitignore.read_text(), end='')
pathlib
— . !