Und obwohl Leute, die Python-Skripte verwenden, um eine Einkaufsliste zu schreiben oder Mietdaten zu kompilieren, nach Kopf kompilieren, aber wenn es so kommt, dass Sie Skripte verwenden, um Routineaufgaben zu lösen, und Skripte manchmal unannehmbar lange funktionieren, besteht die Idee darin, faule Berechnungen zu verwenden zu allem, was sich bewegt, wird es Ihnen gefallen.
In den vorherigen Kapiteln meines Briefes habe ich die Funktionsweise der Evalcache-Bibliothek kostenlos beschrieben.
Link: Festplatten-Caching von Lazy Computing-Bäumen
Um Sie nicht mit der Notwendigkeit zu langweilen, dieses Material vor dem Lesen zu studieren, eine kurze Zusammenfassung des letzten Teils:
evalcache verpackt Daten, Funktionen und Methoden in faulen Objekten. Jedes faule Objekt hat einen speziellen Hash-Schlüssel, der durch die Methode seiner Konstruktion gekennzeichnet ist. Operationen können an faulen Objekten ausgeführt werden, was zur Erzeugung neuer fauler Objekte führt. Diese Operationen sehen genauso aus wie Operationen mit normalen Daten, aber in Wirklichkeit werden keine Berechnungen durchgeführt. Stattdessen wird ein Baum von faulen Objekten erstellt, die sich aufeinander beziehen und sich an ihre Operationen und ihre Argumente erinnern. Wenn Daten abgerufen werden müssen, wird eine Operation ausgeführt, um das verzögerte Objekt zu öffnen, wodurch entweder die Berechnungskette aktiviert wird oder das Ergebnis aus dem Cache abgerufen wird, wenn das Objekt mit diesem Schlüssel zuvor berechnet wurde.
Über einige Änderungen
Seit dem Schreiben des letzten Artikels hat evalcache einige zusätzliche Mechaniken erhalten.
Nicht zwischengespeicherte Ausführungsmechanik
Es stellt sich heraus, dass der Hash eines faulen Objekts so nützlich ist, dass Sie ihn in einer Situation verwenden möchten, in der das Zwischenspeichern des Objekts selbst unmöglich und unnötig ist.
Zu diesem Zweck wurde eine spezielle Syntax eingeführt:
lazyhash = evalcache.LazyHash()
In dieser Version wird das Objekt sofort zum Zeitpunkt der Erstellung berechnet, es wird jedoch trotzdem eine verzögerte Datei zurückgegeben. Auf diese Weise können Sie Berechnungsbäume erstellen, ohne einige Objekte zwischenspeichern zu müssen.
Implizite Offenlegungsmechanik
Implizite Offenlegung ist das erwartete Verhalten eines Memoizers. Obwohl evalcache ursprünglich nicht zum Auswendiglernen, sondern zum Arbeiten mit Berechnungsbäumen entwickelt wurde, kann eine implizite Offenlegung basierend auf evalcache-Algorithmen erreicht werden. onuse
zwei neue Optionen für onplace
und onuse
eingeführt. onplace führt zur Offenlegung des verzögerten Objekts unmittelbar nach der Erstellung und zur Verwendung, wenn versucht wird, es in einigen der für das verzögerte Objekt zulässigen Vorgänge zu verwenden.
import evalcache lazy = evalcache.Lazy(cache={}, onuse=True)
Wir sprechen jedoch nicht über diese unnötige Ergänzung, die die Bibliothek anderen Kreditgebern ein wenig ähnlicher machen soll. Und über faule Dateien:
Faule Dateien
Evalcache enthält ein Add-In zum Löschen von Funktionen, die Dateien generieren. Ursprünglich sollte diese Funktionalität verwendet werden, um die Erstellung von Screenshots zu vereinfachen. Wie sich später herausstellte, können Sie mithilfe der Mechanik fauler Dateien andere interessante Dinge tun.
import evalcache import evalcache.lazyfile lazyfile = evalcache.lazyfile.LazyFile(cache = evalcache.DirCache(".evalfile")) @lazyfile(field="path") def foo(data, path): f = open(path, "w") f.write(data) f.close() foo("HelloWorld","data.dat")
Wie funktioniert es ...
Im Allgemeinen ist die Arbeitslogik dieselbe wie bei allen faulen Objekten.
foo("HelloWorld","data.dat")
Beginnt mit der Erstellung eines faulen Objekts, dessen Hash-Schlüssel an die an ihn übergebenen Argumente gebunden ist. Danach werden die Mechanismen der impliziten Offenlegung angewendet, was zu einem sofortigen Beginn der Berechnung führt.
Aber dann ändert sich die Vorgehensweise.
@lazyfile(field="path")
Lazyfile-Dekorateur analysiert einen Parameter mit dem im Feld angegebenen Namen. Der Dekorateur erwartet, dass bei Ausführung der Funktion eine Datei entlang dieses Pfades erstellt wird. evalcache nimmt diese Datei und erstellt einen festen Link dazu im Hash-Verzeichnis ".evalfile"
. Der Name der Hardlink-Datei entspricht dem Hash-Schlüssel des Lazy-Objekts. Wenn sich später eine Datei mit diesem Namen im Cache befindet, erstellt evalcache beim Erweitern des Objekts anstelle des Aufrufs der Funktion einfach eine feste Verknüpfung an der erforderlichen Stelle mit der vorhandenen Datei im Cache.
Es ist nützlich, dass eine Lazy-Datei ein gewöhnliches Lazy-Objekt ist und andere Lazy-Objekte zum Generieren verwendet werden können.
import evalcache import evalcache.lazyfile lazy = evalcache.lazy.Lazy(cache = evalcache.DirCache(".evalcache")) lazyfile = evalcache.lazyfile.LazyFile(cache = evalcache.DirCache(".evalfile")) @lazyfile(field="path") def foo(data, path): f = open(path, "w") f.write(data) f.close() @lazy def datagenerator(): return "HelloWorld" foo(datagenerator(),"data.dat")
Anwenden der Lenifizierung auf die Videobearbeitung über das Moviepy-Tool.
Wie Sie wissen, kann jede Aufgabe mit einem Python-Skript gelöst werden. Die Anzahl der Python-Bibliotheken ist so groß, dass es sehr schwierig ist, eine Aufgabe zu finden, die nicht von Python-Modulen abgedeckt wird.
Insbesondere die Moviepy-Bibliothek und das zweistündige Studium der Dokumentation bieten uns einen einfachen und funktionalen Video-Editor. Installation - bitte. Sound zum Aufzwingen - bitte. Spezialeffekte - bitte.
Die Arbeit mit Skripten hat jedoch wie immer einen Nachteil. Jedes Mal, wenn das Skript ausgeführt wird, werden alle Artefakte erneut erstellt. Bei der Installation eines einstündigen Videos kann der Betrieb eines solchen Skripts sehr lange dauern.
Die Verwendung der Evalcache-Bibliothek half dabei, Anpassungen an diese Situation vorzunehmen.
Was ist da
Wir verwenden nicht zwischengespeicherte Ausführungsmechanismen, da kein Wunsch oder Bedarf besteht, sich mit dem Zwischenspeichern von Moviepy-Objekten zu befassen. Auf diese Weise erhalten wir alle Vorteile von faulen Objekten für die Verfolgung von Änderungen im Ausführungsbaum.
Wrap-Bibliotheksaufrufe in Lenificators:
LazyVideoClip = lazyhash(VideoClip) VideoFileClip = lazyhash(VideoFileClip) AudioFileClip = lazyhash(AudioFileClip) CompositeVideoClip = lazyhash(CompositeVideoClip) concatenate_videoclips = lazyhash(concatenate_videoclips)
Mit dieser Konstruktion generieren wir Dateien:
@lazyfile("path") def lazy_write_videofile(path, clip): clip.write_videofile(path)
Nachdem wir die erforderlichen Vorgänge für die Videosequenz ausgeführt haben, schreiben wir Teile unseres Clips in separate Dateien. Mit und ohne Musik:
lazy_write_videofile("part0.mp4", part0) lazy_write_videofile("part1.mp4", part1) lazy_write_videofile("part2.mp4", part2) lazy_write_videofile("part0_mus.mp4", part0.set_audio(music.set_duration(part0.duration))) lazy_write_videofile("part1_mus.mp4", part1.set_audio(music.set_duration(part1.duration))) lazy_write_videofile("part2_mus.mp4", part2.set_audio(music.set_duration(part2.duration)))
Diese Dateien werden nur neu kompiliert, wenn sich die entsprechenden Ausführungszweige ändern.
Wenn das Ergebnis vollständig ist, sammeln Sie die Teile mit der Option 'Kompilieren' in einer großen Datei:
if len(sys.argv) > 1 and sys.argv[1] == "compile": clip.lazy_write_videofile("clip.mp4", clip)
Anstelle einer Schlussfolgerung:
Dieser Text zeigt, wie Sie mithilfe der Evalcache-Bibliothek einen Algorithmus, der die Dateierzeugung voraussetzt, vereinfachen können.
Mit diesem Ansatz können Sie die Abhängigkeit von spezieller Software verringern oder das Schreiben komplexer Logik der selektiven Baugruppe vermeiden.
Referenzen:
Github-Projekt
Pypi-Projekt