Warum sollten Sie Pathlib verwenden

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')) #   Python 3.6+ chdir(str(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 — . !

Source: https://habr.com/ru/post/de453862/


All Articles