Gleichzeitige Programmierung in Python | Max S | Skillshare
Drawer
Suchen

Playback-Geschwindigkeit


  • 0.5x
  • 1x (normal)
  • 1.25x
  • 1.5x
  • 2x

Gleichzeitige Programmierung in Python

teacher avatar Max S, Power through programming

Schau dir diesen Kurs und Tausende anderer Kurse an

Erhalte unbegrenzten Zugang zu allen Kursen
Lerne von Branchenführern, Ikonen und erfahrenen Experten
Wähle aus einer Vielzahl von Themen, wie Illustration, Design, Fotografie, Animation und mehr

Schau dir diesen Kurs und Tausende anderer Kurse an

Erhalte unbegrenzten Zugang zu allen Kursen
Lerne von Branchenführern, Ikonen und erfahrenen Experten
Wähle aus einer Vielzahl von Themen, wie Illustration, Design, Fotografie, Animation und mehr

Einheiten dieses Kurses

    • 1.

      Gleichzeitige Programmierung Intro

      0:46

    • 2.

      Threading, Multiprocessing, Async Intro

      13:52

    • 3.

      Gewindegang in Python

      18:52

    • 4.

      Erstellen einer Threading

      14:58

    • 5.

      Einen Wikipedia erstellt

      14:05

    • 6.

      Erstellen eines Yahoo Finance Readers

      16:23

    • 7.

      Warteschlangen und Masterplaner

      15:06

    • 8.

      Einen Postgres Worker erstellen

      21:54

    • 9.

      Integration des Postgres Workers

      20:11

    • 10.

      Yaml Intro

      18:30

    • 11.

      Erstellen eines Yaml

      30:54

    • 12.

      Unseren Wiki verbessern

      28:21

    • 13.

      Alle Arbeiter verbessern und Überwachung hinzufügen

      29:01

    • 14.

      Endprogramm bereinigung

      7:13

    • 15.

      Verriegeln

      12:06

    • 16.

      Multiprocessing Intro

      7:27

    • 17.

      Multiprocessing Warteschlangen

      7:35

    • 18.

      Multiprocessing Pool

      10:40

    • 19.

      Multiprocessing Pool Mehrere Argumente

      4:05

    • 20.

      Multiprocessing Mehrere unterschiedliche Argumente

      4:45

    • 21.

      Multiprocessing Checking Elemente In Der Liste In Bestimmten Bereichen

      6:28

    • 22.

      Einführung in das Schreiben von asynchronen Programmen

      12:10

    • 23.

      Asynchrone Aufgaben

      6:30

    • 24.

      Async

      7:39

    • 25.

      Async verwenden

      3:12

    • 26.

      Asynchroner für Schleifen erstellen

      3:00

    • 27.

      Asynchroner Bibliotheken

      10:28

    • 28.

      Die Async

      10:06

    • 29.

      Async und Multiprocessing kombinieren

      12:14

  • --
  • Anfänger-Niveau
  • Fortgeschrittenes Niveau
  • Fortgeschrittenes Niveau
  • Jedes Niveau

Von der Community generiert

Das Niveau wird anhand der mehrheitlichen Meinung der Teilnehmer:innen bestimmt, die diesen Kurs bewertet haben. Bis das Feedback von mindestens 5 Teilnehmer:innen eingegangen ist, wird die Empfehlung der Kursleiter:innen angezeigt.

150

Teilnehmer:innen

--

Projekte

Über diesen Kurs

In diesem Kurs lernst du, wie du in Python multi-threaded erstellt hast, damit deine Programme noch schneller laufen können.

Wir gehen in eine Einführung vor, wo mögliche speed herkommen und wie wir diese Probleme lösen könnten, und dann tauchen wir direkt in die technischen Inhalte ein und erstellen ein multi-threaded das Daten aus dem Internet erfasst, Parsen und in einer lokalen Datenbank speichert.

Den lecture findest du in diesem GitHub-Repository .

Triff deine:n Kursleiter:in

Teacher Profile Image

Max S

Power through programming

Kursleiter:in

Skills dieses Kurses

Entwicklung Programmiersprachen Python
Level: Intermediate

Kursbewertung

Erwartungen erfüllt?
    Voll und ganz!
  • 0%
  • Ja
  • 0%
  • Teils teils
  • 0%
  • Eher nicht
  • 0%

Warum lohnt sich eine Mitgliedschaft bei Skillshare?

Nimm an prämierten Skillshare Original-Kursen teil

Jeder Kurs setzt sich aus kurzen Einheiten und praktischen Übungsprojekten zusammen

Mit deiner Mitgliedschaft unterstützt du die Kursleiter:innen auf Skillshare

Lerne von überall aus

Ob auf dem Weg zur Arbeit, zur Uni oder im Flieger - streame oder lade Kurse herunter mit der Skillshare-App und lerne, wo auch immer du möchtest.

Transkripte

1. Intro der Concurrent: Hey, da und willkommen. Mein Name ist Max, Gründer von Codierung mit Max und Data Checkpoint. Und in diesem Kurs werden wir über die parallele und parallele Programmierung in Python gehen. Wir werden lernen, wie wir Threading-Programme schreiben können, wie wir Multiprocessing-Programme schreiben können und wie wir auch asynchrone Anwendungen schreiben können. Und wir werden durchmachen, und wir werden tatsächlich ein sehr großes Thread-Programm aufbauen , das Daten von Yahoo Finance lesen wird , um einen Prozess zu erhalten und dann in Datenbanken hochgeladen. Und dann werden wir auch Multiprocessing-Programme schreiben, damit wir sicherstellen können, dass wir alle CPU-Kerne, die auf Ihrem Computer verfügbar sind, optimal nutzen können. Und dann werden wir auch lernen, wie wir asynchrone Anwendungen schreiben können, wie sie funktionieren und wofür Sie diese verwenden können. Damit hoffe ich, Sie drinnen zu sehen. 2. Threading, Threading, Async Intro: Hey, es ist Max und willkommen. In diesem Modul werden wir über die gleichzeitige Programmierung lernen. Bevor wir jetzt einspringen und einige coole Programme schreiben, lassen Sie uns einfach schnell einen Überblick bekommen und einen Überblick darüber, was wir hier abdecken werden, damit wir alle vorbereitet sind und allgemein verstehen, was wir tun werden. Zunächst einmal ist der Umriss für diese Lektion zuerst, dass wir nur eine kurze Einführung in die Parallelität haben, nur einige Beispiele betrachten und warum es sogar cool ist und warum wir es vielleicht verwenden möchten. Und dann gehen wir einfach auf einige Überlegungen über Dinge, die wir im Hinterkopf behalten müssen , wenn wir darüber nachdenken, gleichzeitige Programme zu schreiben. In Ordnung? Wenn wir also Programme schreiben, ist es sehr wahrscheinlich, dass wir sequentielle Programme schreiben werden. Also passiert eine Sache nach dem anderen. Und die meiste Zeit sind wir im Grunde fast die ganze Zeit, so weit es geschrieben ist nur mit einer einzigen CPU. Das bedeutet also, dass wir nicht wirklich alle Ressourcen nutzen , die uns zur Verfügung stehen. Werfen wir einen Blick auf dieses Beispiel hier. Nehmen wir an, dass unsere Maschine vier Kerne hat und wir ein Python Programm ausführen. Und im Grunde, was wir tun, ist, dass wir mehrere Metriken berechnen. Wir haben Datenquellendatei von irgendwo, und wir wollten nur einige verschiedene Metriken berechnen. Die Art und Weise, wie wir dieses Programm ausführen lassen können, ist zuerst, wir berechnen die erste Metrik dann berechnen wir die zweite, dann berechnen wir die dritte, und dann speichern wir alles in einer Datei. Und wenn wir vier Kerne haben, bedeutet das, dass einer unserer Kern dieses Programm laufen wird und die anderen im Leerlauf sitzen. Nun gibt es natürlich noch andere Überlegungen. Wissen Sie, wenn wir das auf unserer persönlichen Maschine laufen, weil wir andere Anwendungen offen haben, et cetera, et cetera. Aber wenn wir in einer Cloud-Umgebung oder so wären und wir tatsächlich mehr CPU-Ressourcen zur Verfügung haben, dann könnte es sein, dass wir nicht alle diese Ressourcen voll ausschöpfen. So könnte stattdessen getan werden, ist, dass wir ein Programm haben könnten, das metrische Spiel berechnet. Und ich habe die Größen hier geändert, um die verschiedenen Metriken anzuzeigen , die eine andere Zeit benötigen, um zu berechnen. Sie haben also eine Metrik, die auf dem ersten Kern ausgeführt wird. Und wir haben Metrik B, die zur gleichen Zeit auf dem zweiten Kern berechnet wird. Und dann haben wir metrische SI, die zur gleichen Zeit auf dem dritten Kern berechnet wird. Da diese Metriken voneinander unabhängig sind, können wir sie alle gleichzeitig berechnen. Es gibt keinen Grund, dass wir warten müssen, bis einer fertig ist. Und dann machen wir die zweite und dann machen wir die dritte. Wir könnten sie alle zur gleichen Zeit berechnen. Und dann, wenn jeder von ihnen fertig ist, könnten wir sie auch einfach in eine Datei schreiben. Und wenn wir es wollten, könnten wir alle Dateien zusammenführen oder etwas, das wir auch tun können, ist, dass wir normalerweise das Speichern in einer Datei ersetzen können, anstatt indem wir in eine Datenbank schreiben. Das wird also eine Metrik berechnen und dann schreiben wir sie in die Datenbank und dann, wissen Sie, dieser Teil ist fertig. Also in diesem Fall haben wir hier ein CPU-intensiveres Programm. Es gibt eine Menge Berechnung vor sich, auf den Engpass sind wirklich die Berechnungen. Und so in diesem Fall ist es gut, unsere verschiedenen Kerne zu nutzen sind verschiedene Rechenressourcen, so dass wir mehr Berechnungen gleichzeitig durchführen können. Aber es gibt auch andere Programme, die wir schreiben können, wo es nicht so viel Berechnung ist, aber tatsächlich eine Menge Zeit, die das Programm verbracht hat, wartet nur auf Netzwerkantworten. Also zum Beispiel, etwas, das wir tun könnten, ist, dass wir verlangen könnten, dass ich von irgendwo komme. Dies könnte eine API sein. Dies könnte von einem Webschaber sein, Punkte, Sie wissen schon, schlagen Website. Aber wie auch immer, wir fordern nur Daten von irgendwo an. Und dann warten wir auf die Antwort, nur um zu uns zurückzukommen. Und dann haben wir jetzt die Daten zur Verfügung. Und dann können wir es entweder in eine Datei schreiben, zum Beispiel, oder wir können es in eine Datenbank schreiben und in eine Datenbank laufen tatsächlich sendet dann die Anfrage zu sagen, okay, schreiben Sie dies und warten Sie dann, bis die Netzwerkantwort. Ja. Ok, es steht geschrieben. Und dann, wenn wir das für mehrere Datenstücke tun und vielleicht fordern wir das erste Stück Daten an und warten dann auf die Antwort auf sie, wir schreiben es und dann können wir das zweite Stück Daten anfordern, auf die Antwort warten, und dann schreibe es. Und die Schrift selbst hat wieder, das Recht abgeschickt und dann darauf gewartet, dass es bestätigt wird. In diesem Fall verbringen wir nur viel Zeit damit, darauf zu warten, dass Dinge passieren. Wir verbringen viel Zeit damit, nur auf Bestätigungssignale zu warten. Ja, ja. Hier sind deine Daten. Okay, es steht uns endlich zur Verfügung, zum Beispiel, wie man über das Netzwerk übertragen wird. Oder los geht's, ja, Die Daten wurden nun in der Datenbank gespeichert. So können wir haben, in diesem Fall können wir mehrere Threads haben. Wir haben also immer noch alles, was auf einer einzigen CPU in einem einzigen Kern läuft. Aber wir haben mehrere gleichzeitige Programme, die auf demselben Kern laufen. Also können wir einen Haupt-Thread haben , der im Grunde, wenn es nichts anderes tun will, vorher einige Dinge passieren kann, aber wirklich kann es einfach Oliver Child-Threads starten. Und was der erste untergeordnete Thread tun wird, ist, dass er Daten anfordern wird. Und während es wartet, kann der zweite Thread dann anfordern, dass es Theta ist. Und dann, wenn die Daten hereinkommen, dann kann der erste Thread sagen, okay, jetzt habe ich meine Daten und ich werde das in eine Datenbank schreiben. Und dann verbringt es Zeit, wieder zu warten. Und während ein Thread auf Netzwerkkommunikation wartet, kann der andere Thread auf Netzwerkbestätigungen arbeiten. Und so können Sie hier sehen. Wir haben zwei Threads, die gleichzeitig ausgeführt werden, die ganze Art von Ausschalten. Eine Anforderung der Daten und wenn sie im Leerlauf sind, wenn es nur darauf wartet, dass das Netzwerk eine Antwort darauf gibt, kann der andere Thread ausgeführt werden. Jetzt gibt es ein weiteres Beispiel für Dinge, die passieren können, ist, dass wir viel Schreiben in Datenbanken haben können. Also eine Sache hier, natürlich, wie wir tun können, ist, dass wir Threads verwenden können, wieder um mehrere Threads zu haben, jeder von ihnen Rechte für eine Datenbank. Und während dieser Thread darauf wartet, dass die Datenbank eine Bestätigung gibt, kann der andere Thread sein Recht initiieren, et cetera. Jetzt können wir auch ein asynchrones Programm verwenden, bei dem Sie grundsätzlich das Recht senden und dann mit dem Programm fortfahren. Und wann immer Sie die Bestätigung erhalten, dann kommen Sie irgendwie zurück zu diesem Teil fertig und bewegen Sie mit dem Programm. So wird Ihr Programm nicht durch diese Netzwerk-E/A-Kommunikationszeiten blockiert, sondern Sie schreiben nur in die Datenbank. Wie Sie hier auf der rechten Seite sehen können. Also schreiben wir in die Datenbank, und während wir auf die Bestätigung warten, initiieren wir einfach das zweite Recht auf eine andere Datenbank und dann können wir vielleicht sogar in eine dritte Datenbank schreiben. Und so geht das alles weiter und im Hintergrund warten wir, bis wir eine Bestätigung von einer der Datenbanken hören , in die wir geschrieben haben. Und wann immer wir diese Bestätigung bekommen, können wir mit diesem Teil des Programms fortfahren. Und so hilft uns das wirklich viel Zeit zu sparen, die wir sonst nur im Leerlauf sitzen würden , um auf die Netzwerkkommunikation zu warten. Jetzt mag das nicht wie eine große Sache erscheinen, denn, wissen Sie, Internet-Geschwindigkeiten können sehr schnell sein. Aber wenn Sie eine Menge Netzwerkkommunikation tun , als ob Sie eine Reihe von Werten schreiben. Wenn Sie also eine Reihe von Anfragen senden, kann Ihr Programm viel Zeit damit verbringen, einfach nur im Leerlauf zu sitzen und zu warten. Und wenn wir diese Option haben, Threads zu verwenden, um Dinge zu tun, während wir warten oder mehrere CPU-Kerne verwenden zu können, wenn wir rechenintensive Operationen haben, kann dies wirklich ein großer Vorteil für uns sein und es kann unsere Programme beschleunigen dramatisch. Nun gibt es natürlich einige Nachteile und Überlegungen, die wir hier machen müssen. Das erste, was wir als Python beachten müssen , hat etwas, das als globale Interpretersperre bekannt ist, was im Grunde bedeutet, dass wir nur einen Thread gleichzeitig ausführen können. So können Sie hier sehen, wenn wir zum Beispiel zurückkehren, wenn wir uns den Kind-Eins-und Kind-Thread zu wildem Kind-Thread anschauen, initiiert man die Anfrage für die Daten. Kapitel 2 ist eigentlich im Leerlauf. Es initiiert nicht seine eigene Anfrage. Es wird nur Uhr gehalten. Ziel eins ist inaktiv, wo es wartet. Dieser untergeordnete Thread T2 kann zum Beispiel mit der Arbeit beginnen. Sie sind also nicht genau gleichzeitig, aber die Threads wechseln sich ab. Und wann immer man im Leerlauf ist, kann ein anderer einspringen und diese CPU-Zeit in Anspruch nehmen. Und so, wenn etwas untätig ist, ist das irgendwie, wenn sie reinkommen können. Es ist also keine perfekte Parallelität, aber natürlich bekommen wir immer noch dramatische Beschleunigungen, weil wir nicht die ganze Zeit mit dem Warten verbringen müssen und während wir warten, machen wir nichts anderes. Jetzt gibt es auch ein wichtiges Thema. Wir müssen darüber nachdenken, dass nicht alles threadsicher sein kann. Also im Grunde wäre threadsichere Mittel, dass es in Ordnung ist, dass mehrere Threads mit einer bestimmten Entität zu tun haben. Oder unsere Threads beschäftigen sich mit Daten so, dass sie andere Bedrohungen nicht stören. Nun, eine Möglichkeit, wie wir über die Gewindesicherheit gehen können, ist die Verwendung von Sperren. Auf andere Weise schreiben Sie auch nur threadsichere Programme, die nicht zu seltsamen Dingen führen , wenn mehrere Threads versuchen, darauf zuzugreifen, zum Beispiel ein Stück Daten freizugeben. Eines dieser Dinge, die wir bekommen können, wenn wir keine Thread-Sicherheit haben , ist etwas, das als Race-Bedingung bezeichnet wird. Dies ist etwas, das Sie hier in Threads sehen werden, aber möglicherweise auch auftreten, wenn Sie wissen, dass Sie über Datenbanken lernen. Aber im Grunde ist eine Race-Bedingung, wenn zwei separate Programme oder Entitäten oder Threads in diesem Fall versuchen, auf die gleichen Daten zuzugreifen und zu ändern oder sogar nur die gleichen Daten zu verwenden. Nehmen wir zum Beispiel an, wir haben zwei Threads, die beide eine Variable a verwenden und Thread liest man die Variable und modifiziert sie dann und gleichzeitig, oder kurz vor oder kurz nach dem Thread um auch in die Variable und schreibt dann darauf. Und es gibt sehr viele verschiedene Dinge, die passieren können. Nehmen wir zum Beispiel an, jeder dieser Threads erhöht nur die Variable. Wenn unsere beiden Threads sie fast gleichzeitig lesen, werden sie beide den gleichen Wert sehen. Und dann ein Thread, eine Art von setzt sein Ergebnis n und erhöht es einfach um eins. Thread 2 hat diesen neuen Wert nicht gesehen, hätte aber den vorherigen Wert gesehen. Und wenn es es um eins erhöht, wird es nur insgesamt um eins erhöht und nicht um zwei, weil sie beide einem ähnlichen Zeitpunkt lesen, bevor einer der anderen seine Operation beendet hat. Und dann können Sie natürlich andere Variationen von grundsätzlich dem gleichen Problem haben. Wenn Sie die Variable entweder überschreiben, führen Sie einen Downstream-Vorgang durch, z. B. Addition oder Multiplikation, und dann verwenden Sie sie später nicht. Aber weil Threads gleichzeitig stattfinden, ist es sehr schwer für uns, genau zu wissen. Es ist grundsätzlich unmöglich für uns zu wissen, auf welcher Thread zuerst zugegriffen wird, besonders wenn wir diese über verschiedene Durchläufe desselben Programms kennen. Wenn wir also unser Programm erneut ausführen, kann dies zu unvorhersehbaren Ergebnissen führen, da manchmal ein Thread es zum ersten macht und manchmal ein anderer Thread zuerst dorthin kommt. Und manchmal haben wir vielleicht eine Wettkampfbedingung. Manchmal können wir nicht, weil sie auch externe Faktoren im Spiel sind. Und so. Bedingungen des Rennens können zu sehr unvorhersehbaren Ergebnissen führen. Und so ist es sehr wichtig , dass Sie, wenn Sie Daten geteilt haben oder so etwas, dass Sie immer darüber nachdenken müssen, wenn Sie Daten geteilt haben. Thread-Sicherheit ist das Programm, das ich schreibe, kann sich selbst stören. Und wenn Sie andere Module oder Bibliotheken in Python verwenden und einige von ihnen speziell sagen, diese Entität, zum Beispiel ist diese Klasse, die Sie verwenden, threadsicher oder diese Klasse ist nicht threadsicher. Und so müssen Sie sich bewusst und vorsichtig sein weil dies zu sehr, sehr seltsamen, kniffligen und komplizierten und verwirrenden Bugs führen kann , die schwer zu reproduzieren und sehr schwer zu finden sind. Also die andere Sache, die zu berücksichtigen ist, ist zunächst über Thread zu sprechen. Insbesondere laufen Threads auf einem einzigen CPU-Kern und sie alle teilen den gleichen Speicher, weshalb wir dieses Problem der Thread-Sicherheit und Race-Bedingungen haben. Und es gibt auch einen kleinen Overhead, der mit nur dem Threadwechsel zwischen den verschiedenen Threads verbunden ist, sowie nur das Management der Threads bei der Selbsterstellung, Abreißen von Threads. Während für Multiprocessing und was wir haben, ist, haben wir verschiedene dasselbe Programm, das auf verschiedenen CPU-Kernen läuft, oder den gleichen Teil dieses Programms, das auf verschiedenen CPU-Kernen läuft. Und in diesem Fall haben wir eigentlich keinen gemeinsamen Speicher. Jeder einzelne Prozess hat seinen eigenen Python Interpreter und seine eigene globale Interpretersperre. Das ist natürlich großartig, weil wir nicht einige dieser Probleme haben müssen , die wir zum Beispiel mit Bedrohungen haben. Aber es gibt auch mehr Speicher. Es gibt auch mehr Overhead damit verbunden. Einer davon ist also, einen Großteil der Speicherauslastung erneut zu duplizieren. Und es gibt nur viel mehr Speicher, der verwendet werden muss, um all diese verschiedenen Prozesse über die verschiedenen Interpreter hinweg zu erstellen und zu replizieren . Und nur über Parallelität im Allgemeinen, es ist sehr cool und es kann sehr nützlich in schnell sein. Wir wollen auch sicherstellen, dass die Programme, die Sie schreiben, tatsächlich werden es wert sein, zu schreiben und eine gleichzeitige Art und Weise. Weil das Schreiben und Debuggen gleichzeitiger Programme sehr komplex werden kann und es manchmal schwierig wird , Probleme in Ihrer Logik zu finden oder bestimmte Probleme aufgrund all dieser Parallelität zu debuggen. Also ja, mit Betrachtung der Parallelität können wir definitiv erstaunliche Beschleunigungen bekommen. Aber denken Sie auch daran, dass nicht jedes Programm gleichzeitig sein muss. Und es ist völlig in Ordnung, du weißt schon, einfach weiter viele sequentielle Programme zu schreiben. Aber dann wirst du bemerken wie, Oh mein Gott, ich verbringe so viel Zeit damit, auf all das zu warten, nicht funktioniert. Ich kann hier wirklich Multithreading nutzen, oder es gibt keinen Grund für mich, diese 80 Metriken sequenziell zu berechnen. Ich werde nur Multiprocessing verwenden und vier oder zwei oder acht verwenden oder viele Kerne schweben , die Sie entweder auf Ihrem Computer oder in der Cloud-Umgebung zur Verfügung haben und den Prozess beschleunigen. Also sind sie definitiv Schreibsituationen, um es zu benutzen. Aber es gibt auch, wissen Sie, dass wir nicht jedes einzelne Programm gleichzeitig schreiben müssen. Denken Sie also daran, weil Parallelität dem Schreiben und der Logik und auch dem Debugging Komplexität hinzufügt . 3. Thread in Python: Na gut, also lasst uns weitermachen und unser erstes Hintergrundprogramm schreiben. Wir fangen mit dem Threading an. Jetzt werde ich PyCharm dafür verwenden, aber Sie können natürlich voran gehen und sich frei fühlen, was auch immer Ihre Lieblings-Codierumgebung ist. Ich mag es, PyCharm zu verwenden, wenn wir mehrere Dateien haben, die ich tatsächlich enden werde, weißt du, in Richtung des späteren Teils gehen, während wir durch das Threading voranschreiten. Also ja, ganz wie mit Tortendiagramm dafür zu arbeiten. Ansonsten, wissen Sie, wenn ich ein schnelles Testen und Prototyping mache und ich manipulieren muss oder irgendwie auf eine Menge Daten zurückblicken möchte, die während eines Programms erstellt wurden oder einfach nur irgendwie mit Dingen herumspielen. Dafür benutze ich normalerweise gerne eine Spinne oder Jupyter Notizbücher. Aber abgesehen davon genieße ich PyCharm sehr. Auch hier liegt das ganz bei Ihnen. Also habe ich gerade einen Ordner auf meinem Desktop hier erstellt , wo wir all unsere Arbeit speichern werden. Ich werde eine neue Datei erstellen und diese Box aufrufen. Ich nenne das nur mein Haupt, aber du kannst es nennen, wie immer du willst, solange er die Punkt-Py-Erweiterung hatte. Und ich werde hier etwas tun, das Sie wahrscheinlich viel in Python Programmen sehen werden. Und wir werden anfangen, eine Hauptfunktion zu definieren. Und wir werden hier vorbeigehen, was uns im Grunde sagen lässt, dass wir später darauf zurückkommen. Also, jetzt wird es nichts tun. Wir werden hier die Syntax haben. Wenn Unterstrich, Unterstrich, Name, Unterstrich, Unterstrich, ist Unterstrich gleich. Und dann haben wir Unterstriche. Unterstrich, Unterstrich, Unterstrich, Hauptunterstrich, Unterstrich. Und dann werden wir die Hauptfunktion ausführen. Nun, im Grunde, was diese Syntax bedeutet, ist, dass, wenn dieses Programm direkt ausgeführt wird, nicht, wenn es importiert wird oder irgendetwas, nur eines dieses Programm speziell ausgeführt wird. wird das hingerichtet. Andernfalls, wenn wir dies importieren, wird es nicht ausgeführt. Das ist also nur Koordinatenaugen-Syntax. Ich mag es sehr. Und das werden Sie wahrscheinlich in vielen Python Programmen sehen. Natürlich ist es nicht vollständig notwendig, aber es ist irgendwie nett, wenn Sie den Code testen möchten , den Sie hier selbst schreiben, wenn er ihn irgendwie ausführen möchte. Andernfalls, wenn Sie es importieren möchten, möchten Sie nicht, dass es ausgeführt wird. In Ordnung, also haben wir hier unsere Hauptfunktion. Und im Grunde, was wir tun werden, ist, dass wir zwei Funktionen schreiben werden. Die erste Funktion wird die Summe der Quadrate berechnen. Also werden wir es def nennen, Summenquadrate berechnen und es wird eine Eingabe haben. Wir können vorerst „n“ sagen. Wir definieren das in einer Sekunde. Und unsere zweite Funktion wird nur ein wenig schlafen. Und dann werden wir nur zur Verfügung stellen, und hier die Eingabe und Sekunden für wie lange wir möchten, dass es schlafen. Und das werden wir auch in einer Sekunde definieren, denn zuerst müssen wir nur das Zeitmodul importieren, das uns erlaubt, diesen Schlaf zu machen. Also meine ich funktionale modifizieren das in einer Sekunde. Also für einen Schlaf ein wenig, alles, was wir hier tun werden, ist, dass wir die Schlaffunktion nennen. Und wir werden einfach so viele Sekunden schlafen. Für die Summe der Quadrate berechnen, werden wir nur eine Summenquadratvariable haben, die wir auf 0 initiieren werden. Wir werden eine for-Schleife für mich in Reichweite haben. Und in jeder Iteration werden wir nur unsere Summe der Quadrate auf dieser Zahl quadriert haben . Und dann am Ende, lassen Sie uns einfach die Summe der Quadrate hier ausdrucken. Ok? Also jetzt in unserer Hauptfunktion, Lassen Sie uns voran und haben 24 Schleifen. Ich werde sagen, für mich im Bereich fünf, wir werden nur die Summe der Quadrate berechnen. Und das wird unser Beitrag hier sein. Und wir werden eine zweite Funktion haben, die für mich in Reichweite sagen wird, angefangen von einem, Sex zu gehen. Also schlafen wir tatsächlich die erste Iteration, wir werden Schlaf ein wenig nennen. Und wir werden unseren Wert haben, höre ich. Und wir werden auch Timer haben, die wir einrichten wollen. Also werden wir die Berechnungszeiten unseres Programms messen. Und dafür können wir auch das Zeitmodul verwenden. Also werden wir unsere Berechnung Startzeit wird als der aktuelle Zeitstempel in diesem Moment definiert werden . Und dann, wenn dies getan ist, werden wir sagen, die Berechnung der Summe der Quadrate nahm. Und dann nehmen wir uns die Zeit im aktuellen Moment abzüglich des Zeitstempels, den wir in diesem Moment haben. Und wir haben zuerst unsere Variable hier gespeichert. Nun, das wird uns eine Ausgabe mit vielen Dezimalzahlen geben. Also, was wir stattdessen tun werden, ist, dass wir die runde Methode verwenden, und wir werden sie nur auf eine Dezimalstelle runden, Ort, um diese Art von reduziert ein wenig, ein bisschen sauberer zu bekommen. Und was wir dann für Schlaf-Kleinigkeiten tun werden, machen wir eine ähnliche Sache. Wir werden schlafen, fangen Sie an. Zeit, die auch nur das Tracking sein wird, die Zeit in diesem Moment, Speichern Sie sie auf eine Variable. Und dann wieder hier schlafen wir. Hat die aktuelle Zeit abzüglich der Startzeit genommen. So lange hat es gedauert. Und die Berechnungen tatsächlich zu haben, brauchen einige Zeit. Wir werden dir nicht nur in die Augen legen, aber lass uns voran gehen und das werde ich plus 1 sein, zuallererst. Und dann werden wir es auch mit 1 Million multiplizieren, nur damit es ein wenig Zeit braucht. Jetzt können wir das erledigen. Klicken Sie zum Beispiel auf Ausführen hier. Und es wird, nun, beginnen, das sequentielle Programm für uns zu laufen. Und so können wir hier sehen derzeit die Summe der Quadrate ist bei der Arbeit und dauerte etwa sieben Sekunden, gerundet auf eine Dezimalstelle, die wir hier sehen können. Und jetzt wird unser Programm einfach iterativ schlafen. Also 1 Sekunde, 2 Sekunden, drei Sekunden, vier Sekunden, fünf Sekunden. Und am Ende davon werden wir sehen, okay, also dauerte der ganze Prozess 15 Sekunden. Insgesamt dauerte unser Programm ungefähr 21 Sekunden oder 22 Sekunden. Sie haben 15 hier plus sieben. Also waren sieben von denen für die Berechnung und 15 davon für den Schlaf. Okay, das ist also ein sequentielles Programm. Also lasst uns voran gehen und versuchen, etwas Parallelität hier hinzuzufügen. Wir werden Threading dafür verwenden. Also werden wir Threading importieren. Nun, das Schöne ist, Threading ist eigentlich Teil der Standard-Python Installation. Sie müssen also nicht wirklich etwas anderes installieren. Sie können es einfach direkt importieren. Jetzt für jede dieser Schleifen hier, werden wir dies jetzt stattdessen durch einen Thread ersetzen. Also werden wir in jedem dieser Fälle tun, ist, dass wir einen Thread erstellen und wir werden es t nennen, wird nur unsere kurze Variable für Thread sein, bedrohlichen Punkt-Thread und andere mehrere Variablen, die wir hier definieren müssen. Das erste, was ist das Ziel, das die Funktion sein wird, die ausgeführt werden muss. Und dafür wird es für diesen Fall die Summe der Quadrate berechnen. Hinweis: Ich setze die Klammern nicht am Ende. Es ist nur der Funktionsname, weil wir ihn noch nicht nennen wollen. Dies ist irgendwie der Verweis auf die Funktion. Dann können wir auch die Argumente für unsere Funktion zur Verfügung stellen. Wir haben hier ein separates Schlüsselwort, args, und dies erwartet ein Tupel. Da wir also nur ein Eingabeargument haben, werden wir hier unseren Eingabewert haben. Und dann gehen wir zu o. Lassen Sie uns unsere, definieren wir unseren Maximalwert wird dies hier sein, nur um es zu haben und nicht ein bisschen kürzer zu sein. Und so wird unser Eingabetupel das sein, aber sagt, es muss ein Tupel sein. Wir müssen hier ein zusätzliches Komma setzen, um sicherzustellen, dass es ein Tupel der Größe eins ist. Dann werden wir das kommentieren. Und dann machen wir das Gleiche hier. Wir werden einen Thread erstellen. Und wir werden es zum Ziel haben, den Schlaf eine kleine Funktion. Und das Eingabeargument, das es geben wird, ist dieses Auge hier. Und lassen Sie uns das einfach in Sekunden umbenennen. Wir müssen nicht wissen, dass diese Namen identisch sind. Das brauchen wir nicht. Das macht nur ein bisschen schöner zu lesen. Also werde ich das wieder in Sekunden umbenennen, machen Sie dies zu einem Tupel. Und wir werden das kommentieren. Nun, wenn wir das ausführen, wird es ein wenig überrascht sein, denn eigentlich wird sie noch gar nichts haben. Und der Grund dafür ist, dass wir tatsächlich die Threads initiieren müssen. Das nächste, was wir tun müssen, ist, dass jeder Thread t dot aufrufen muss. Fangen Sie an So wie das. Jetzt können wir das ausführen und wir werden immer noch ein bisschen seltsames Ergebnis bekommen. Also gehen wir weiter und sehen uns das an. Beachten Sie also, wie unser Programm weitergeführt hat. Und dann haben wir die Druckausgänge. Und dann ist das hier. Und dann haben wir die Summen ausgedruckt. Also ist das offensichtlich nicht, wie lange Ihr Programm dauerte weil noch andere Dinge los sind. Aber das liegt nur daran, dass die Threads gleichzeitig ausgeführt werden. Was wir also wollen, ist das, was wir wollen, dass Programm blockiert wird , um zu warten, bis alle Threads fertig sind. An diesem Punkt. Dies ist, wenn alle Threads fertig werden müssen. Und dann wollen wir ausdrucken, wie lange das gedauert hat. Um das zu tun, werden wir eine, eine andere Variable einrichten. Soll es eine Liste sein. Wir werden jeden dieser Threads im Auge behalten und dann nur sicherstellen, dass unser Programm blockiert, bis sie alle fertig sind. Also nennen wir diese Variable aktuelle Bedrohungen. Und wieder, Sie können es nennen, was auch immer. Und jedes Mal, wenn wir einen Thread erstellen, werden wir hier den Thread anhängen, so dass wir ihn später referenzieren können. Jetzt werden wir unsere Liste durchlaufen. Und für jedes Element, das der Thread hier selbst ist, werden wir dot join nennen. Nun, was Dot Join tut, ist, dass die Ausführung blockiert, bis dieser Thread fertig ist. Also wir iterieren darüber und wir rufen im Grunde Dot Join auf, was bedeutet, dass nichts passieren darf, bis dieser Thread beendet ist. Also kann es im Grunde nicht weiter als das gehen. Also haben wir das hier gemacht. Jetzt gehen wir weiter und machen das Gleiche hier. Also lassen Sie uns einfach diese Variable wiederverwenden und diese wiederverwenden. Lassen Sie mich das hier setzen. Und dann werden wir Dot Join aufrufen, um sicherzustellen, dass unser Programm blockiert ist. Und dann warten wir darauf, dass das beendet ist, bis wir das dann ausführen. Wenn wir also fortfahren und das jetzt ausführen, können wir es jetzt sehen, in Ordnung, also läuft unsere Hinrichtung tatsächlich wie erwartet. Und jetzt haben wir unseren Schlaf, okay, also etwas Interessantes zu bemerken. Hören Sie das ein bisschen schneller, aber, wissen Sie, wirklich nichts, worüber Sie sich freuen können. Und das ist wirklich nur, weil dies eine rechenintensive Methode ist. Und so werden Sie die meiste Zeit nicht wirklich irgendwelche Performance-Verbesserungen in Bezug auf wie nur Rechenmaterial hier bekommen . Also wirklich nichts, was alles zu faszinieren hier. Und wenn wir in diesem Abschnitt Verbesserungen beschleunigen wollten, dann müssen wir zur Multiprocessing gehen, da wir verschiedene Kerne verwenden können. Aber hier, weil jede Art von Thread nur auf einmal ausgeführt werden kann und das CPU-intensiv ist, wirklich all diese Berechnungen, gibt es nicht viel IO. Ähm, also, weißt du, es passiert sowieso irgendwie sequentiell. Aber das coole Ding ist hier, und das Schlafen ist, dass Krankheit ein sehr, sehr einfaches Beispiel ist. Das Schlafen geschieht auf einer Thread-Ebene, so dass ein anderer Thread ausgeführt werden kann, während jeder dieser Threads im Leerlauf sitzt. Anstatt eine Gesamtzeit von 15 Sekunden zu nehmen, was unser sequentielles Programm nahm. Es dauert nur fünf Sekunden, was im Grunde der längste Schlaf ist, den wir hatten. Das Maximum hier ist fünf. So können wir in diesem Fall sehen, natürlich ist dies das sehr, sehr einfache Beispiel. Wir werden viel nützlicher sein, um nicht zu schlafen oder zu programmieren. Aber stattdessen wissen Sie, wenn dies eine Art Netzwerkverbindung ist, wie eine API-Anfrage machen, Schreiben in eine Datenbank von einer Datenbank oder, wissen Sie, was auch immer, etwas Schweres in Netzwerk-IO, das verbringt nur dort, wo unsere Threads gerade sind, wo unser Programm viel Zeit damit verbringt, im Leerlauf zu sein, nur auf die Netzwerkkommunikation zu warten und vielleicht der Server auf der anderen Seite seine Sache zu tun und dann die Antwort zurückzusenden. Jetzt haben wir irgendwie die Grundlagen der Erstellung von Threads hier für verschiedene Funktionen gesehen, aber ich wollte Ihnen einige andere Dinge zeigen, die ich für interessant halte. Das erste ist also, was passiert wäre wenn wir statt Join am Ende hier aufzurufen, es stattdessen hier nennen würden. Also lassen Sie uns voran und rufen t dot join hier. Und gehen wir weiter und führen das erneut aus. Also, was passiert in diesem Fall? Jetzt ruft dieser hier immer noch den Join am Ende an. Aber wieder, das ist wie eine CPU. Die Funktion oder intensiv in Anführungszeichen natürlich, aber Sie wissen, CBO konzentriert. So können Sie hier im Grunde sieben Sekunden sehen, was genau das ist, was wir vorher hatten. Auch hier erwarten wir keine Veränderung. Aber in diesem Fall, was passiert, ist der Join-Aufruf hier bedeutet tatsächlich, dass die Ausführung blockiert ist. Nein, diese Schleife wird nicht fortgesetzt. Die Ausführung wird blockiert, bis dieser Thread beendet ist. Jetzt kommen wir zurück zu den 15 Sekunden, die wir vorher hatten. Weil wir nicht alle diese Threads starten und sie laufen lassen und dann das Programm am Ende blockieren, bis alle diese Threads fertig sind. Stattdessen starten wir einen Thread und blockieren dann die gesamte Ausführung, bis diese Bedrohung erledigt ist. Während wir vorher alle Threads gestartet haben und dann die Ausführung blockiert haben, bis alle Threads fertig sind. So können Sie hier sogar nur eine leichte Syntax sehen, den Join hier statt hier zu haben. In diesem Fall ist ein sehr großer Einfluss auf uns. Es gibt noch eine Sache, die ich dir zeigen wollte. Wenn wir die gemeinsamen Erklärungen herausnehmen, das ist eigentlich das, was wir nicht angefangen hatten. Und wenn wir uns daran erinnern, wenn wir das erneut ausführen, bekommen wir diese seltsame Sache, bei der wir, wissen Sie, das Programm irgendwie seine Sache macht, den Hauptthread hier. Und jetzt bekommen wir tatsächlich den ganzen Druck und tatsächlich geschieht der Schlaf auch für diese verschiedenen Threads. Also haben wir 10 verschiedene Threads, die fünf von hier laufen. Nun, eigentlich 11, weil dies unser Hauptprogramm hier sein wird, das Hauptprogramm, erstellen wir hier fünf zusätzliche Threads. Fünf zusätzliche Fäden hier. Und dieser hier endet, als im Grunde, wissen Sie, seine Sache zu tun es ist nicht blockiert, diese Drucke, und dann läuft dieser. Und es druckt die Summe der Quadrate aus. Und in der Zwischenzeit schlafen diese fünf Fäden einfach. Wir drucken keinen Sinn, also sehen wir ihn nicht. Also etwas, das Sie auch passieren können, ist, dass Sie hier einen Daemon Fly hinzufügen und dies auf wahr setzen können. Und wir können das Gleiche hier machen. Jetzt wird das interessant, wenn wir das ausführen. Denn was passiert, ist, dass wir durch den Hauptthread laufen und sobald der Hauptthread beendet ist, stoppt das gesamte Programm. Was also das Daemon-Flag hier bedeutet, ist, dass, sobald der Hauptthread fertig ist, alle Damon Flags Autor. Und es spielt keine Rolle, ob sie fertig sind oder nicht. Wenn ein Thread kein Daemon-Thread ist, muss jeder Thread beendet werden. Jeder Nicht-Damon droht zu beenden, bevor das ganze Programm beendet werden kann. Aber Damon Threads müssen nicht fertig sein, damit das Programm beendet wird. Sobald der Hauptthread fertig ist, dann, wenn irgendwelche Daemon-Threads oder links, ist es nicht wirklich wichtig. Das hält das Programm nicht davon ab, zu beenden. Das ist also eine interessante Sache, weißt du, abhängig von der Situation, die du kannst oder willst, oder du willst es nicht. Aber seien Sie sich bewusst, dass der Aussage Flug hier bedeutet, dass diese Threads, wenn das Programm beendet ist, das Hauptprogramm beendet. Und wenn etwas ein Daemon-Thread ist, bedeutet das, dass es nicht beendet wird, es wird einfach aufhören, das Programm ist fertig. Während wenn wir das Daymond-Flag auf false haben, dann müssen diese Threads auch fertig sein, bis das gesamte Programm beendet werden kann, was genau das ist, was wir vorher hatten. Also, während das läuft, lass mich das einfach zurücklegen. Jetzt gibt es natürlich eine interessante Sache, die wir mit Gelenken verwenden können. Wenn wir wieder beigetreten sind, bedeutet die gemeinsame Anweisung, dass der Thread, den jeder dieser Threads, auf die wir den Join aufrufen , beendet werden muss, bevor wir an diesem Punkt fortfahren können, weil es im Grunde bis alle diese Threads fertig sind. Also, wenn wir dies erneut ausführen, obwohl dies Damon-Threads ist, weil wir diese gemeinsamen Anweisungen aufrufen, die die weitere Ausführung blockieren. Im Grunde stellen wir sicher, dass die Programme fertig sind. So können wir sehen, dass wir irgendwie zu den vorherigen Ergebnissen zurückkommen, die wir hatten. Und wir können das noch weiter nehmen, um zu sagen, anstatt über Oliver-Threads zu gehen, vielleicht blockieren wir nur, bis die ersten drei fertig sind. Und so ist unser Schlaf hier. Wir würden erwarten, dass dies drei Sekunden dauern wird, da die anderen beiden Damon-Drohungen sind. Und so kann es auch weitermachen. Aber die ersten drei werden eigentlich schlafen und die Hinrichtung blockieren. So können Sie hier sehen, dass genau das ist, was wir bekommen. Die ersten drei blockieren die Ausführung, sobald der dritte Thread dieses Abschnitts beendet ist, was einen Ruhezustand für drei Sekunden darstellt, das Programmkontingent wird fortgesetzt, es wird beendet, und die einzigen verbleibenden Threads sind Damon-Threads. Also ist das ganze Programm fertig. 4. Einen Threading erstellen: In Ordnung, also haben wir gerade das Schreiben unserer ersten Art von Thread-Programm beendet. Nun, was wir tun werden, ist, dass wir ein bisschen festklemmen und wir werden diese in Klassen verwandeln. Und ich zeige Ihnen, wie wir tatsächlich Klassen zum Threading verwenden können. Also, um dies zuerst tatsächlich zu tun, um ein neues Verzeichnis zu erstellen. Und hier werden wir nur haben, dass unsere verschiedenen Arbeiter verschiedene Threads sind, nur um, du weißt schon, eine gewisse Struktur zu haben. Und dann hier wird dies unsere Summe sein oder Summe der Quadrate berechnen Funktion wird im Grunde in eine Klasse gesetzt werden, so dass wir wiederverwenden können. Es macht nicht so viel Sinn für diesen Anwendungsfall, sondern für andere allgemeinere Zwecke. Das wird also r quadriert sein, einige Arbeiter dot py, nur für den Fall, dass wir mehrere haben wollen. Und dieser hier werden wir noch einen haben, der deine Schlaffunktion sein wird. Also werden wir es r haben, Schlaf Marker sein. Und ich werde auch zu und, und unterstreichen, unterstreichen, init, underscore dot py file, die dieses Verzeichnis hier für mich in ein Python Modul verwandeln wird , aus dem ich importieren kann. Also müssen Sie hier nicht einmal etwas einfügen, aber es wird mir nur erlauben, aus diesem Verzeichnis zu importieren. Alles klar, also lassen Sie uns voran und beginnen mit r quadriert. Irgendein Arbeiter. Zuerst werden wir Threading importieren. Und dann werden wir eine Klasse erstellen. Es wird r quadrierte Summe Arbeiter sein. Und dieser Arbeiter wird von Threading Punkt Bedrohung erben. Es ist also irgendwie von der Thread-Klasse hier erben. Und dann werden wir die Initialisierung der Klasse definieren. Und wir werden dieses Schlüsselwort super verwenden. Normalerweise vervollständigt es einfach automatisch. Also gehen wir hin. Und wir gehen für die Initialisierung der Elternklasse, wir werden nur die Super-Methode verwenden. Nun, die Super-Methode hier, definieren wir nur die Klasse, die die Eltern haben, die wir initialisieren möchten. Und dann nennen wir uns selbst hier und dann nennen wir Punkt darin. Und im Grunde werden alle Elternklassen , von denen diese Klasse erbt, dann initialisiert. Wir müssen also nicht jede einzelne übergeordnete Klasse separat initialisieren. Wir können einfach die vollständige Initialisierung aller Elternklassen wie folgt aufrufen, was sehr praktisch ist. In diesem Fall haben wir natürlich nur eine Klasse, aber, wissen Sie, wenn wir mehrere hier hatten und wir wollten sie einfach ohne weitere Probleme initialisieren. Dann können wir es so machen. In Ordnung? Und dann, was wir hier drin haben ist, dass wir eine berechnete Summe von Quadraten haben. Also werden wir das übernehmen. Und weil es eine Klasse ist, müssen wir hier selbst einbauen. Und so wird all diese Methode hier tun, ist, die Summe der Quadrate genau so zu berechnen , wie wir sie vorher hatten. Jetzt gibt es eigentlich zwei verschiedene Möglichkeiten, wie wir dies tun können. Eine Möglichkeit ist, dass wir die Eingabe hier lassen können , so dass wir sie einfach durch diese Klassenmethode zur Verfügung stellen können. Oder die andere Möglichkeit, dass wir es tun können, ist, dass wir es Teil der Initialisierung der Klasse sein können. Und dann können wir ein Attribut der Klasse festlegen. Und dann haben wir hier keine Eingabe. Und es ist feucht, verweisen Sie einfach auf das Attribut. Nun, in diesem Fall ist es nicht wirklich wichtig. Es kann tatsächlich sauberer sein, es hier zu benutzen. Aber anstatt es einfach so zu haben, ist eigentlich eine Art Syntax, die ich sehr mag. Denn dann, wissen Sie, wenn Sie eine weitere Methode schreiben, haben sie am Ende wie viele Eingabeparameter. Auf diese Weise können Sie einfach Ihre Werte initialisieren. Ihr IQ kann einfach Ihre Klasse für alle Werte initialisieren und dann nur interne Parameter referenzieren anstatt sie an alle diese verschiedenen Methoden übergeben zu müssen, wenn es zu diesem Punkt kommt. Also werden wir tatsächlich diese Methode verwenden. Und jetzt gibt es noch etwas, das wir tun können, nämlich wir können Stern-Quarks machen. Und was das bedeutet, ist, dass dies eine Zuordnung von Schlüsselwertpaaren für zusätzliche Schlüsselwortargumente sein wird, die wir möglicherweise übergeben möchten. Dies könnte zum Beispiel Name gleich sein, und dann was auch immer der Eingabename sein wird. Und dann können wir, weißt du, wie Persona. Ich weiß nicht, woher das kam, aber Sie können einfach all diese anderen Eingabeparameter haben. Und anstatt jedes der Berge zu definieren, das es offen lässt, können wir tatsächlich nur dieses Stern-Schlüsselwort, Argumente sein. Und vielleicht gibt es Parameter, die wir tatsächlich in das Threading übergeben wollen , das wir setzen möchten. Und so können wir diese Schlüsselwortargumente einfach weiter hier weiterleiten. Und so ist es wirklich schön, weil wir all diese Initialisierungsparameter bereitstellen können , die einfach an übergeordnete Methoden weitergegeben werden können, oder wir können sie auch selbst verwenden. Nun, etwas anderes, das wir tun müssen, ist, dass wir unseren Thread starten müssen. Also müssen wir das tun, um sicherzustellen, dass es tatsächlich läuft. Jetzt ist das Interessante, wenn wir den Thread starten, wirklich, wenn Sie die Berechnung durchführen möchten, müssen wir es in die Run-Methode einfügen. Also, wenn wir eine Run-Methode haben und wenn wir self.age star aufrufen, weil wir von der Thread-Klasse erben. Es wird den Thread starten und ich werde einfach anfangen, die Run-Methode auszuführen. Und so können wir die Run-Methode überschreiben, die wir von der Thread-Klasse erben , um das Laufen für uns zu machen. Also in diesem Fall werden wir eigentlich nur die Summe der Quadrate berechnen. Also werden wir diese Methode nicht einmal nennen. Wir werden nur die Klasse erstellen und dann wird es das Laufen für uns durchführen. Okay, also noch eine kleine Syntax-Sache hier. Ich werde nur einen Unterstrich hinzufügen, weil nur um anzuzeigen, dass es eine Art interne Methode ist, die wir intern in der Klasse verwenden werden . Ordnung, das wird also unsere Fadenklasse sein, 4 Quadrat, ein Marker. Jetzt machen wir das Gleiche für unseren Schlaf Yorker. Also wieder hier werden wir Threading importieren. Wir werden die Klasse schläfrig Marker erstellen, die von Threading Dock Thread erben wird. Wir werden die Klasse initialisieren und die Elternklasse initialisieren. Und wir werden Schlüsselwortargumente zulassen, die wir an die Initialisierungen der Elternklassen weitergeben werden. Und dann auch hier, wo wir setzen können, ist Sekunden für wie lange? Für wie viele Sekunden wollen wir, dass das schläft, das heißt, wir werden natürlich eine Sekunde benutzen. Also hier werden wir schlafen. Eine kleine Funktion, die nur Zeitpunktschlaf auf der Sekundenvariablen aufrufen wird. Jetzt werden Sie eine schöne coole Sache bemerken, die PyCharm hier für mich getan hat, ist, dass wir das Zeitmodul-Buch nicht importiert haben, weil , wissen Sie, es ist leicht verfügbar. Möchten Sie das irgendwie als eine Option erkennen, die wir es benutzten, es hat tatsächlich das Wichtige für mich getan, aber ansonsten natürlich, wissen Sie, stellen Sie sicher, dass Sie das Zeitmodul importieren. In Ordnung, also schlafen wir für die Anzahl der Sekunden, die wir bei der Initialisierung hier bestanden haben. Und dann werden wir nur die Run-Methode überschreiben, um Sleep aufzurufen, eine wörtliche Methode, die wir gerade hier definiert haben. Also, wenn wir zurück zu unserer Hauptfunktion gehen, brauchen wir das Einfädeln nicht mehr und setzen hier, ich denke, du wirst uns wiedersehen. Wir werden, von Arbeitern punktschläfrigen Arbeitern, wir werden unseren Stadtarbeiter importieren. Und von Arbeitern Punkt Quadrat von einem Arbeiter, dass wir nach Concord gehen, R-quadriert einen Arbeiter. Okay, jetzt können wir die Erstellung dieser Schleife hier ersetzen , indem wir nur unsere Klasse initialisieren. Also werden wir unseren verschlafenen Arbeiter eine Instanz von verschlafenen Arbeitern haben. Und wir werden eine Hoffnung wollen, die unten gehen. Hier. Wir haben r quadriert, einige Arbeiter, die eine Instanz der Quadratwurzel einige Arbeiter sein wird. Und wir werden den Maximalwert hier als Eingabeparameter haben. Und was wir jetzt für den Join tun werden, ist für aktuelle Threads. Benennen wir dies in aktuelle Arbeiterklumpen um. Technisch gesehen das Gleiche, was wir hier haben. Wir werden unseren Arbeiter verfolgen, den wir hier initialisiert haben. Und wieder, wir werden nur die Join-Methode hier aufrufen , um eine Art von Block, bis diese Ausführung von diesem getan. Und dann tun wir dasselbe für unseren verschlafenen Arbeiter. Und hier sind, Sekunden werden die Sekunden sein, die ich hier zur Verfügung stelle. Und das können wir auskommentieren, so dass wir es in einer Sekunde referenzieren können. Und wieder hier können wir dies einfach ändern, um unsere derzeitigen Arbeiter zu sein, die jede der Instanzen, die wir hier haben, einschließen wird. Und dann rufen wir Dot Join wieder an. In Ordnung, also gehen wir weiter und führen das aus. So. Ich erkenne, dass AMI, wir sollten genau dasselbe tun. Und es sieht so aus, als hätten wir hier ein Problem gestoßen. Lassen Sie uns also sehen, wo das Problem auf unseren Join-Methoden liegt um zu sagen, dass wir einer Bedrohung nicht beitreten können, bevor sie begonnen hat. Also wahrscheinlich vergessen, den Thread hier intern zu starten , weil wir es hier nicht mehr nennen. Also lasst uns das noch einmal versuchen. Alles klar, da gehen wir. Wir haben also unsere Ausführungsausgabe hier, und wir haben unseren Schlaf, der momentan nur drei Sekunden seit ewig ist. Habe immer noch diese Syntax hier, das Minus zwei. Also können wir hier sehen, dass wir nur waren , weißt du, in diesem Fall war es ziemlich einfach. Wir haben nur ihre zwei Funktionen hier genommen und jede von ihnen in eine separate Klasse gebracht, was natürlich für diesen Fall nicht so viel Sinn ergibt. Aber wenn Sie komplexe Dinge tun, wie Sie wissen, möchten Sie bestimmte Werte in eine Datenbank schreiben. Und ein Teil dieses Prozesses besteht darin, alle Werte zu strukturieren und sie so zu formatieren, dass sie sich in der richtigen Struktur befinden und dann in die Datenbank hochgeladen werden. Dann, wenn Sie einen bestimmten Datenbank-Worker haben, kann einfach die Rohwerte eingeben und es wird nur die Daten für Sie strukturieren. Und dann führen wir das Hochladen durch. Und all das ist irgendwie verborgen von unserer Hauptfunktion wird innerhalb jeder Klasse selbst betreut. Und natürlich nennen wir hier immer noch die Punkt-Joins in jedem dieser, nur um die Ausführung zu blockieren. Jetzt können wir hier sehen, oder wir können nicht bauen. Wir werden es in einer Sekunde sehen. Denken Sie daran, dass wir diese Dan Parameter hatten und wir können immer noch dasselbe tun, weil wir die Schlüsselwortargumente weitergeben. Wir können Damon hier wahr machen. Und dann, weil unser schläfriger Arbeiter all diese Schlüsselwortargumente akzeptiert und sie weitergibt, wird es dies nehmen, weil es ein Schlüsselwortargument ist oder einen bestimmten Wert findet, wird es dies nehmen und es an den Elternteil Klassen, die in diesem Fall nur der Thread ist. Es wird also den Daemon-Parameter auf true gesetzt, was natürlich wir das Effektive sehen können, wenn wir den Join Call hier entfernen. Also lassen Sie uns voran und führen Sie dieses noch einmal aus, nur um den Effekt des Hinzufügens dieses Schlüsselwort-Argument-Parameters oben hier zu sehen . So können Sie hier sehen, dass der stamen Parameter dann an das übergeordnete Element weitergegeben wurde , da wir die Join-Methode nicht mehr aufrufen. Wir erhalten genau das Gleiche, was wir in der vorherigen Lektion gesehen haben. Eine andere Sache, die wir auch tun könnten, ist, wenn wir nur wollen , dass alle diese Klassen immer Daemons sind. Wir können hier auch den Daemon-Parameter einstellen , der den gleichen Effekt hat. Außer natürlich ist in diesem Fall die Logik vor uns verborgen, was vielleicht nicht das Beste ist, und wir haben nicht wirklich viel Kontrolle darüber, es sei denn, wir wissen ausdrücklich , wonach wir suchen, und wir aktualisieren das Attribut der Klasse sich selbst. Aber eigentlich ist etwas Wichtiges zu wissen, dass der Daemon-Parameter gesetzt werden muss, bevor Sie die Start-Methode aufrufen. Da wir also auch start hier aufrufen, wenn wir unseren Worker nehmen und Daymond auf false setzen, wird es nicht funktionieren, weil der feuchte Parameter gesetzt werden muss , bevor wir den Thread starten, was wir in einem Zweiter hier. Also, ja, da gehen wir. Wir erhalten den Fehler dafür. Also natürlich, wissen Sie, verstecken ist nicht das Beste, und es ist besser, wenn wir das tun wollten, es mit der Schlüsselwort-Argument-Option weiterzugeben, die wir hier haben. Und in diesem Fall machen wir es nur ein wenig sauberer, weil diese Funktionen vor allem nicht mehr hier sind, aber es gibt Methoden der Klasse selbst. Und, wissen Sie, all diese Logik wird irgendwie an jeden der verschiedenen Arbeiter in Anführungszeichen weitergegeben , die wir hier haben, sie alle machen ihre eigene eigene Arbeit, verantwortlich für eine separate oder spezifische Sache. Und so sagen wir einfach, in Ordnung, wir werden rennen, dieser Arbeiter wird das tun. Und wir haben den Join am Ende hier nicht angerufen. Wir werden die Arbeiter leiten. Es wird etwas Bestimmtes tun. Und wirklich ist das Hauptprogramm nur für die Ausführungsreihenfolge und allgemeine Logik. Während sie alle große Verarbeitungssachen mögen. Wir müssen diese Datei nicht überladen und sie sehr groß machen. Wir können hier jede von ihnen in separate Dateien oder in separate Klassen einfügen. Und dann, wissen Sie, wenn wir uns die spezifische Logik ansehen müssen, dann wird sie alles in dieser einen Datei enthalten sein. Alles, was für die Ausführung jeder dieser Klassen relevant ist. 5. Erstelle einen 10 a: In Ordnung, jetzt, da wir irgendwie die Grundlagen für unsere Threading-Klassen erstellt haben. Lassen Sie uns voran gehen und in das eigentliche Projekt springen, das wir tun wollen , um dieses Threading und einen nützlicheren Weg zu implementieren. Also, was wir tun werden, ist, dass wir die Liste der S- und P-500-Unternehmen auf dieser Seite hier nehmen werden. Und wir werden nur durch all diese Symbole scrollen. Und dann für jedes Symbol, das wir hier haben, besuchen wir einfach die entsprechende Yahoo Finance Seite. Und wir werden diesen aktuellen Preis genau hier extrahieren. Und dann werden wir diese Dinge in einer Datenbank speichern. Und so ist der Prozess, den wir hier haben, im Grunde haben wir drei Dinge vor sich, die irgendwie unabhängig arbeiten können. Und es wird eine Menge Netzwerk-Zeug geben , von dem wir wirklich nicht blockiert werden wollen. Das erste, was wir tun können, ist, dass wir uns von hier aus einfach die Liste der Unternehmen holen können. Und wirklich, was das mit sich bringt, ist nur eine Anfrage an hier. Und dann scrollen Sie einfach durch diese Tabelle und nehmen Sie immer nur den ersten Eintrag heraus. Sobald wir jeden dieser Einträge haben, können wir dann eine Anfrage hier an die Website stellen und diesen Wert herausbekommen. Das ist also nur eine Netzwerkanforderung, die auf diesen Wert wartet und ihn extrahiert. Und sobald wir diesen Wert haben, können wir ihn in die Datenbank einfügen. So können wir sehen, dass dies wahrscheinlich eine wirklich schöne Anwendung zum Threading wäre , wenn wir dies so schnell wie möglich machen wollen, denn es gibt eine Reihe von Netzwerk-Zeug, wissen Sie, Laden von Seiten, die darauf warten, in die Datenbank einfügen und die Bestätigung warten. Und es gibt nicht wirklich viele CPU-Aufgaben. Also, ja, Um dies zu tun, wir einfach anfangen, indem wir die Klasse schreiben, die uns erlaubt, die Einträge von hier zu extrahieren. In unseren Arbeitern werde ich hier einen neuen Arbeiter schaffen. Und wir nennen es einen Wiki-Arbeiter. Und dafür werden wir die Anforderungsbibliothek verwenden, um die Anfragen tatsächlich zu erledigen. Und wir werden auch Beautiful Soup benutzen. Wenn Sie mit Beautiful Soup nicht vertraut sind oder wenn Sie es irgendwie vergessen haben, und stellen Sie sicher, dass Sie einfach überprüfen Sie die Web Scrapping Klasse wieder. Aber ansonsten ist die Bibliothek ziemlich unkompliziert. Also einfach irgendwie damit durchzugehen. Es sollte relativ einfach sein, etwas mitzuverfolgen. Wir werden unsere Wiki-Arbeiterklasse hier haben. Und wir werden unsere Initialisierungsmethode haben. Und wirklich, was wir hier tun können, ist für den Moment, wir können einfach hart codieren, um URL zu sein, von der wir scrubben möchten. Ich werde das einfach überschreiben. Und wirklich, wenn wir unsere Klasse erstellen, wir alles, was wir tun werden, ist, dass wir nur ihren Yuan oder L haben, das, du weißt schon, dieses Klassenattribut. Das nächste, was wir tun werden, ist, dass wir eine Klassenmethode erstellen , die S und P 500 Unternehmen bekommen wird. Und was das tun wird, ist, dass es zu gut läuft. Wie die Methode schon sagt, wird es die Firma für uns bekommen. Also werden wir eine Anfrage stellen. Wir werden die Anforderungsbibliothek verwenden, stellen eine GET-Anfrage an unsere URL hier, wie folgt. Und wir gehen nur davon aus, dass alles vor sich geht, aber wir können einfach hier haben und wie, wenn unser Statuscode nicht auf aber wir können einfach hier haben und wie, wenn eine 100 ist und ich werde eine leere Liste zurückgeben und vielleicht können wir ausdrucken, wie ich es nicht bekommen konnte. Und Bäume, weißt du, was auch immer. Das ist einfach einfach einfach. Natürlich können Sie dies auf alle verschiedenen Statuscodes erweitern , die Sie interessieren möchten, oder sogar einige Protokollierung hier durchführen, aber wir werden dies nur für das absolute Minimum haben. Und dann werden wir verwenden, anstatt alles in der gleichen Methode zu haben, lassen Sie uns einfach voran und erstellen Sie eine zweite Methode, die tatsächlich Firmensymbole extrahieren wird . Und das wird in der Seite HTML nehmen. Und diese Methode hier wird die Sache sein, die tatsächlich dafür verantwortlich ist , jedes dieser Symbole herauszubekommen. Also lassen Sie uns voran und schauen Sie sich die Seitenquelle, die Sie entweder tun können, indem Sie hier mit der rechten Maustaste klicken und Seite Quelle oder Befehl Alt J. Und wir suchen, Lassen Sie uns einfach voran und erhalten ein Verständnis für die Struktur. Also suchen wir hier nach dem ersten Symbol, das nur m sein wird, und wenn wir das irgendwie zusammenbrechen, ist das die Tabelle, nach der wir suchen. Und dieser Tisch eigentlich ganz schön, wie wir sehen können. Es gibt also eine Idee, die dieser Tabelle zugeordnet ist. Und wenn wir das nur nachschlagen, dann können wir sehen, dass dies die einzige ID für diese Tabelle ist. Also gibt es keinen Blick auf US oder so etwas auch, was sehr schön ist. Also ja, lass uns weitermachen und unsere schönen Loops erstellen. Schöne Soup Instanz, die die Seite HTML nehmen wird. Und wir werden das L x benutzen ich werde parser. Wir werden das hier nur setzen, weil wir bemerken, wenn wir das hier nicht stellen, werden wir nur eine Warnung bekommen oder nicht einmal eine Warnung, genau wie eine Benachrichtigung. Wir können es für eine Sekunde auslassen, nur um zu sehen. Aber ja, nur spezifizieren, damit wir diese Protokollierung nicht bekommen, was ein bisschen nervig sein kann. Alles klar, das nächste, was wir tun müssen, ist, dass wir zuerst diese Inhaltstabelle finden müssen, und dann werden wir diese Tabelle durchlaufen. Also unser Inhalt oder unser Tisch wird Suppe Punkt finden. Und wir werden nach der ID finden, die die Wähler sein wird. Und ich werde das nur ein bisschen schneller durchgehen da dies eher wie Web-Scraping Sache ist, nicht unbedingt auf das Threading konzentriert, aber nur damit wir einen Arbeiter für uns haben, tatsächlich erhalten Sie diese Inhalte, so dass wir sie weiter verwenden können. Das ist also unser Tisch. Und jetzt, wo wir unsere Tabelle haben, wollen wir über alle Zeilen gehen. Also unsere Tabellenzeilen. Wenn wir in unsere Tabelle gehen, werden wir alle Tabellenzeilen-Tags in unserer Tabelle finden hier. So können wir sehen, dass es einen in der Kopfzeile gibt, und dann gibt es für jede Zeile, wir haben einen hier im Körper. Und dann können wir unsere Tabellenzeilen durchlaufen. So können wir für Tabellenzeile in einer Tabelle Zeilen sagen und wir werden die erste überspringen. Denn Sie werden feststellen, wenn Sie uns testen, dass sich der erste tatsächlich in der Kopfzeile befindet. Und so gibt es hier natürlich kein Symbol zu extrahieren, also überspringen wir das erste. Und dann werden wir für jede Tabellenzeile das Symbol extrahieren, das sein wird, wir werden das erste T d-Tag finden, das wir hier sehen können. Und von hier aus werden wir den Text herausnehmen. Und wir werden auch das Zeilenumbruchzeichen am Ende hier entfernen. Das werden also unsere Symbole sein. Und jetzt können wir entweder diese Mentalisten sammeln und dann die ganze Liste zurückgeben. Oder wir können auch einen Generator verwenden und einfach fühlen oder Symbol. Und dann von hier aus können wir sagen, Ausbeute von Punkt, extrahieren Firmensymbole. Und ich muss nur die Seite HTML DOM übergeben, die nur der Textteil unserer Antwort hier sein wird. In Ordnung, also eine Sache, die tatsächlich bemerkt werden muss, ist, dass wir hier keine Klasseneigenschaft verwenden. Und was wir tun können, ist, dass wir dies tatsächlich zu einer statischen Methode machen können, zu der gehört, im Grunde über alle Instanzen der Klasse geteilt wird. Und dann tun wir es nicht, weil wir keine Klasseneigenschaft verwenden, die sich selbst ist. Ok. Das wird also unser Vicki Arbeiter sein. Aber natürlich, Lassen Sie uns voran und testen dies. Jetzt, weil wir Beautiful Soup benutzen. Wirklich. An diesem Punkt wird es, es wird, ein bisschen schöner sein, wenn wir das später wiederverwenden wollen. Nur um sicherzustellen, dass alle unsere Umgebung, alle unsere Bibliotheken und Sachen irgendwie enthalten sind. Wir werden eine virtuelle Umgebung schaffen. Also werde ich Python minus M gehen, dann jemand, um eine virtuelle Umgebung zu erstellen. Und das aktuelle Verzeichnis, das Ben heißen wird. Drücken Sie Enter, die unsere virtuelle Umgebung für uns erstellen wird. Und das gibt uns im Grunde eine Art frischer Python Installation, die wir verwenden können, was nur wenn wir es aktivieren, es wird ein wenig schöner, weil wir uns dann bewusst sind, welche Bibliotheken wir verwenden, und wir können eine spezifische Anforderungsdatei, so dass alles irgendwie eigenständig ist und nicht von unserem aktuellen System-Setup abhängig ist. Also werden wir fortfahren und unsere virtuelle Umgebung aktivieren. Und wenn wir zum Beispiel in Python gehen, können Sie jetzt sehen, wo in unserer virtuellen Umgebung und ich versuche, diese Klasse zu importieren, bekommen wir tatsächlich ein Problem, weil wir im Moment keinen schönen Supersturm haben. Also werden wir von Arbeitern Dot Wiki, Worker sagen , wir werden Schlüsselarbeiter 0 importieren und sogar Anfrage ist nicht installiert. Also werden wir weitermachen und Pip-Installationsanfragen machen. Und weil wir in unserer virtuellen Umgebung sind, wird eigentlich die Pip-Version aus unserer virtuellen Umgebung verwenden. So können Sie hier die PIP für virtuelle Umgebung sehen. Und das nächste, was wir tun wollen, ist, dass wir auch Beautiful Soup installieren wollen. Also, um dies zu tun, werden wir pip eingeben, das OH installieren, um volle Suppe für. Hier ist kein Typ drauf. Ok, großartig. Und ja, das sind die beiden Bibliotheken, die wir nicht brauchen sollten. Also können wir weitermachen und das versuchen. Noch einmal und großartig. Da gehen wir. Es funktioniert. Wir können das in einer Sekunde testen. Aber lassen Sie uns einfach auch unsere aktuellen Pakete in eine Requirements-Datei schreiben , so dass wir dies gegebenenfalls später neu erstellen können. Okay, also lasst uns voran gehen und dieses Wiki und den Arbeiter testen. Und wir werden eine Instanz von n. machen und dann können wir für Symbol in McKee sagen, Worker Dot bekommt S und P 500 Unternehmen, nur unsere Klassenmethode hier aufrufen. Lass uns einfach weitermachen, ein Symbol ausdrucken und dann unterbrechen wir sie. Generation von einem Tippfehler hier. Ordnung. Wir drucken das Symbol aus und dann brechen wir zusammen. Und ja, los geht's. Das ist jedoch eine Warnung, dass wir so eine Art von wie die Wahl einer bestimmten 12 bekommen. Deshalb können Sie einfach L, x und L reinlegen . Lass es ihnen nicht tun. In Ordnung? Okay, also schauen Sie sich unsere einfache, Ordnung, also haben wir den ersten. Und dann lasst uns einfach eine Symbolliste haben. Und lasst uns das Gleiche machen. Aber lassen Sie uns jedes Symbol in unsere einfache Liste bringen , um sicherzustellen, dass wir am Ende nichts mehr bekommen , wissen Sie, oder so etwas. Und dann werden wir uns die Länge unserer symbolisierten betrachten, die 505 hat, was eigentlich die Anzahl der Unternehmen in diesem ist. Ich weiß, es ist irgendwie verwirrend, weil es 500 sagt und es ist eigentlich 505. Aber das ist großartig, denn genau das haben wir erwartet. Und zwei, keine extra bestätigen diese. Wir können uns den letzten ansehen. Scrollen Sie ganz nach unten. Einmal zu weit. Da gehen wir. Okay, perfekt. Also haben wir jetzt unsere Klasse, um die Symbole zu bekommen. Nun wieder, wir haben das etwas schneller durchgemacht, nur weil wir wieder sicherstellen wollen, dass wir uns darauf konzentrieren, hier einzufädeln und nicht speziell durch den Aufbau von Westkupfern zu gehen. Also, ja, wenn Sie mit Beautiful Suppe vertraut sind und Tücher schneiden, großartig. Und wenn du es nicht bist, hättest du wahrscheinlich sowieso folgen können, da unsere Syntax hier ziemlich einfach ist und wir nur verschiedene HTML-Elemente durchlaufen. Aber wenn Sie eine Auffrischung dazu wollen, wenn Sie diese Mischung lernen möchten, gehen Sie voran und schütteln Sie einfach die Web-Abwrackklasse wieder auf. Aber ja, so jetzt haben wir unsere Wiki-Arbeit sind für uns verfügbar, was wird das erste, was natürlich sein, das wir brauchen. Was uns im Grunde mit all unseren Werten sehen wird, die wir dann verwenden können, um später die einzelnen Unternehmen nachschlagen, indem wir diese URL hier manipulieren. Und dann können wir auch weitermachen und sobald wir diesen Wert hier extrahieren, können wir dann weitergehen und diesen in eine Datenbank senden. Also lasst uns hier für jetzt anhalten und dann weiter mit dem in der nächsten Lektion. 6. Erstelle einen Yahoo a: Alles klar, jetzt, da wir unser Wiki-Worker-Setup haben, lassen Sie uns die Klasse schreiben, die eine Thread-Klasse sein wird, die den Preis aus der Verwendung dieser Yahoo Finance URL hier extrahieren wird. In Ordnung, also werde ich auch diese beiden Arbeiter hier löschen, weil wir sie nicht mehr brauchen. Also lasst uns voran gehen und diese wirklich schnell löschen. Wir werden hier einen neuen Arbeiter schaffen, was Biao sein wird, der den Preis finanziert. Wir nennen das Yahoo Finance Arbeiter. Und dann hier werden wir zuerst Threading importieren, weil wir es verwenden. Aber dann wird es einen yahoo Finance Preisarbeiter haben , der vom Threading Dot Thread erben wird, wie wir es vorher getan haben. Und dann in unserer Initialisierungsmethode werden wir nur sicherstellen, dass dies zu initialisieren. Und wir werden auch Schlüsselwortargumente akzeptieren, die wir hier an unsere Elternklassen weitergeben werden. Ordnung, also hatten wir das vorher. Lassen Sie uns nun auch einfach sicherstellen, dass Sie den Thread starten, damit Sie wissen, dass wir zu diesem Punkt kommen. Und dann werden wir auch die haben, wir werden die Run-Methode überschreiben, aber definieren Sie sie in ein wenig. Okay? Also, was brauchen wir? Nun, wir müssen auch das Symbol akzeptieren, das wir haben wollen. Ich möchte dieses Symbol als Klassenattribut speichern. Und dann brauchen wir auch die Basis-URL, die wir verwenden möchten, die im Grunde alles sein wird, außer für diesen letzten Teil. Das wird also unsere Basis-URL sein. Und dann am Ende hier können wir, naja, tatsächlich, wir können unser Basisjahr hier nur definieren. Und dann werden wir die eigentliche URL als unsere Basis-URL festlegen. Und lassen Sie uns hier formatierte Strings verwenden. Und dann fügen wir das Symbol am Ende hier hinzu. Also ja, wir werden nur unser Basisjahr haben. Ich werde der erste Teil hier sein. Und dann hier drüben, werden wir hinzufügen, dass sie am Ende ähnlich sind. Und so wirklich das hier wird uns nur geben, was auch immer das Symbol ist. Es wird uns im Grunde das gleiche Ergebnis wie dieses geben. Es ist meiner Meinung nach nur ein sauberer Weg, dies auszudrücken. Okay, jetzt haben wir unseren Arbeiter hier, und jetzt wollen wir die Run-Methode überschreiben, was im Grunde das ist, was wir hier tun müssen, ist OK, also jetzt haben wir dieses Urinal. Also, äh, noch einmal, müssen wir diesen Preis hier extrahieren. Also lassen Sie uns in den HTML gehen und versuchen, dies zu finden. Also haben wir es hier an, es ist eigentlich im Titel. Das ist sehr praktisch. Mal sehen, ob es auch woanders ist, aber wir könnten es schon von dort bekommen. Es ist auch hier. Und mal sehen, ob es okay ist. Also auch irgendwo im Skript zurückgegeben. Es gibt also verschiedene Möglichkeiten, wie wir dies tun können. Einer von ihnen ist natürlich, wir können es extrahieren. Wo war das? Von? Wo es auftauchte, wie wir von hier extrahieren können. Aber wenn wir mit der rechten Maustaste klicken und wir den XPath kopieren, und lassen Sie uns einfach voran und werfen einen Blick darauf. Ja, also sieht es nicht nach besonders sauber aus. Es gibt keine spezifische ID oder irgendetwas, was wir hier verwenden können. Und weil es auch im Titel enthalten ist, können wir es nicht einfach von dort extrahieren. Dies ist natürlich, ein wenig abhängig davon, dass Yahoo Art dieses Format behalten. Aber, weißt du, wenn sie es ändern, wie wenn sie auch dieses Format hier oben ändern, müssen wir natürlich auch unsere Abnutzung anpassen oder sowieso. Also lassen Sie uns einfach mit der einfacheren Option für jetzt gehen. Wir werden es hier nur aus dem Titel selbst extrahieren. Ordnung. Also wieder, wir werden aus BS-Ordner importieren. Wir werden importieren und schöne Suppe. Und lassen Sie uns voran und testen Sie dies oder Neuigkeiten. Wir müssen auch das Request-Modul importieren. Und lassen Sie uns einfach voran gehen und dies zum Testen verwenden. Also gehen wir zu gehen setzt unsere URL hier. Wir werden Anfragen importieren, wird sagen, in Ordnung, gleich Anfrage Punkt bekommen unsere URL. Und dann werden wir unsere Suppe eine Instanz von Beautiful Soup sein lassen, indem wir den Text unserer Anfragen aufnehmen. Also habe ich hier einen Tippfehler. Ich war nicht wichtig, wichtig. Versuchen Sie das noch mal. Wir gehen Suppenpunkt-Titel, was uns tatsächlich direkt darauf zugreifen lässt, richtig? Glücklicherweise sieht es so aus, als ob dieser Inhalt dynamisch generiert wird, aber das ist in Ordnung. , um dies auf einen anderen Weg zu gehen. Wir werden stattdessen die L-XML-Bibliothek verwenden. Und wirklich werden wir es nur für eine sehr einfache Sache verwenden, die nur sicherstellen wird, dass wir XPath verwenden können , da es derzeit nicht mit Beautiful Soup unterstützt wird. Also sagen wir von x, ich bin L, x und L, und wir werden HTML importieren. Also bin ich, natürlich haben wir es nicht installiert. Also lassen Sie uns voran und installieren Sie schnell Stand L x L. Dort gehen wir. Ich werde das auf eine Anforderung schreiben. Stellen Sie unseren Python wieder auf, lassen Sie uns versuchen, das zu importieren. Da gehen wir. Und nehmen wir, brauchen Sie keinen schönen Vorgesetzten mehr. Lassen Sie uns voran und haben unsere Sie sind wir gehen, um eine Anfrage und Sonde Anfragen senden. In Ordnung. Und dann werden wir sagen, nun, unsere Seiteninhalte, die wir nennen können, wird HTML von String sein. Also werden wir nur HTML hier aus L XML importieren. Dies wird uns nur helfen, mit XPath zu analysieren. Ich bin wieder, Sie werden feststellen, dass die Syntax sehr einfach ist, also müssen Sie nicht mit dieser Bibliothek vertraut sein. Wir werden nur im Grunde diese beiden Methoden daraus verwenden. Zuerst werden wir hier die Zeichenfolge HTML einfügen, die hier gespeichert werden wird. Und dann hat dies eine Ex-pat x-Pfadmethode, die wir verwenden werden. Und was wir hier tun müssen, ist jetzt, dass wir den XPath dafür bekommen müssen, was wir sehr einfach tun können, indem Sie einfach mit der rechten Maustaste auf XPath kopieren klicken. Also, sobald wir dieses Element hier finden, was wir einfach tun können, indem Sie so suchen, können Sie mit der rechten Maustaste auf Copy XPath und dann fortfahren und das hier einfügen. Und da gehen wir. So können wir sehen, ob wir auf das erste Element zugreifen können, den Text, dann werden wir in der Lage sein, den Wert hier so zu extrahieren. In Ordnung, also lasst uns weitermachen und umsetzen. Also haben wir das getestet, um sicherzustellen, dass wir etwas haben, das funktioniert. Also lasst uns weitermachen und das nochmal tun. Wir werden unseren Brunnen haben, tatsächlich können wir das einfach kopieren, also seit wir es bereits getan haben. Also werden wir zuerst unsere Anfrage ausstellen, die durch das sein wird. Und dann haben wir unsere Seiteninhalte so. Und dann wollen wir so einen Preis haben . Und wir machen hier nicht viel Fehlerbehandlung. Zum Beispiel, was passiert, wenn wir hier keine Antwort bekommen? Dieser Wert kann nicht in einen Gleitkommawert oder was auch immer konvertiert werden. Also natürlich, wissen Sie, wenn Sie dies robuster machen wollen, können Sie hier Statuscodeüberprüfung hinzufügen, wie wir es in unserem Wiki-Worker getan haben. Sie können try-except-Anweisungen hinzufügen, um verschiedene Fälle zu behandeln , in denen Sie möglicherweise nicht immer einen Float-Wert herausbekommen. Aber nur um das einfach zu halten, werden wir es einfach so behalten, ohne zu viel Fehlerbehandlung zu tun. Also, jetzt haben wir unseren Preis, und dann können wir einfach voran gehen und einfach unseren Preis ausdrucken. Okay, also gehen wir zurück in unsere Hauptfunktion hier. Und jetzt werden wir das ein bisschen ändern und unsere zwei Arbeiter importieren und sie einfach ein bisschen zusammenarbeiten lassen. Also hier wollen wir die Yahoo Finance Preisarbeiter importieren. Das erste, was wir tun werden, ist, dass wir eine Instanz unseres Wiki-Arbeiters erstellen. Und wir werden für Symbol in Wiki-Arbeiter sagen, kriege keine S und P 500 Unternehmen. Dies wird uns nur ein einziges Symbol nach dem anderen geben. Und jetzt werden wir eine Instanz des Yahoo Finance Preisarbeiters erstellen. Und das Symbol, das wir hier passieren werden, wird direkt das Symbol sein, das wir hier haben. Und dann, wenn wir eine Liste unserer derzeitigen Arbeiter wollen und behalten, wie wir es gebildet haben. Gezeichnet sind Yahoo Finance, Preisarbeiter. Und dann verwenden Sie einfach die Join-Methode hier. Und nimm das raus. Wir können immer noch ablenkende Zeit machen. Nimm und benenne unsere Variable hier um, um Neustartzeit zu verschrotten. In Ordnung, also müssen wir sicherstellen, dass wir die Instanz ihres Wiki-Arbeiters hier verwenden, nicht nur die Kostendefinition selbst. Also lasst uns übergehen, was wir getan haben. Und im Grunde wenden wir das, was wir gelernt haben, jetzt für das Threading mit unseren beiden Arbeitern an. Also der erste, den wir haben, ist unser Wiki-Arbeiter , der wieder, wenn wir es übergehen, es hat die Hauptmethode, die wir hier verwenden werden, die die S und P 500 Unternehmen bekommen wird, die nur diese senden wird Anfrage. Und für diese Anfrage von den Tabellenelementen, Es ist dies, Ich werde nur das erste Element extrahieren, dem wir annehmen, wird das Symbol sein. Und dass wir als Input weit Yahoo Finance Preis Worker verwenden werden. Und dafür werden wir dann eine Anfrage an diese URL senden. Wir werden aus dem HTML mit dieser XML-HTML-Klasse hier extrahieren. Wir werden dies nur verwenden, damit wir tatsächlich die XPath Art bekommen können, dass dies eine einfache Möglichkeit ist, den XPath zu extrahieren den Preis von hier zu erhalten und ihn in einen Float zu konvertieren. Also werden wir über diese Firmenlisten scrollen, die wir hier haben. Und für jedes Symbol, das wir erhalten, werden wir dann einen Thread erstellen , der diese Anfrage erstellen wird. Und dann wird es nur auf die Ausgabe für jetzt drucken. Also lassen Sie uns dann die Ausführungszeit verfolgen, genau wie wir es vorher getan haben. Und hier rufen wir Join am Ende auf, nur damit im Grunde alles blockiert wird, bis jeder einzelne Thread beendet ist. Und wir müssen hier nicht einmal etwas anderes tun, weil es die hat, wir überschreiben die Standard-Run-Methode, die direkt nach dem Start des Worker passiert. Also, ja, bevor wir das ausführen, möchte ich noch eine Sache implementieren, die nur unseren Umfang etwas verlangsamen wird . Wir werden Zeit importieren und wir werden zufällig importieren, nur damit wir nicht spammen. Wir sagen „Time dot sleep“. Wir werden sagen, 200 zufällige Punkte zufällig. Das bedeutet also, dass jeder Thread zwischen 0 und 20 Sekunden in den Ruhezustand versetzt wird , da dies eine Zufallszahl zwischen 01 erzeugt. Das wird die Dinge nur ein wenig verlangsamen und es wird unser Programm laufen lassen. Nun, ich schätze, an diesem Punkt, dass maximal 20 Sekunden etwas schläft wie 20 Sekunden. Wir können das sogar bis zu 30 drücken, nur um, wissen Sie, nicht Spam Yahoo, während wir das tun. Denn wir werden die Dinge etwas später ändern, um nicht wie Spawnen einen einzelnen Arbeiter für jedes einzelne Symbol, das wir hier haben. Aber ja, und eigentlich möchte ich hier einen zusätzlichen Check implementieren , der sein wird, wenn unser Statuscode 200 ist. Dann für jetzt, lasst uns einfach aufhören. Und, wissen Sie, stoppen Ausführung, so dass wir nicht wie Spanne mit Fehlermeldungen und so. Gehen wir also voran und führen Sie unsere Hauptfunktion aus. Ich werde es diesmal über das Terminal machen, weil ich hier meine virtuelle Umgebung einrichten habe, der alles installiert ist, was ich brauche. Also lasst uns weitermachen und das laufen. Und nach dem Warten ein wenig, Da gehen wir. Also haben wir die Preise beginnen hier reinzukommen. Manche unterbrechen uns. Aber ja, alles funktioniert irgendwie wie beabsichtigt. Ich kann Ihnen garantieren, dass es hier wahrscheinlich einige Fehler gibt, die wir nicht fangen, was auf eine Vielzahl von Gründen zurückzuführen ist, mit denen wir besser umgehen sollten. Aber im Moment werden wir das nur so lassen, wie es vorerst ist. Wir sollten wenigstens so sein, als ob wir das abmelden oder so etwas. Aber was auch immer für jetzt, lassen Sie es einfach so, wie es ist, da der Hauptzweck davon war nur die Threads einzurichten, um tatsächlich die separaten Anfragen zu erledigen. Das sind also die separaten Threads. Damit wir all diese separaten Anfragen erledigen können, damit wir, wissen Sie, nicht durch all diese Netzwerkzeit blockiert werden. Aber in Zukunft werden wir tatsächlich sehen, wie wir Art von Begrenzung und Skalierung und Art definieren können , wie viele Arbeitnehmer wir haben wollen , damit jeder das alles ein bisschen strukturierter anstatt nur Laichen und einzelnen Thread für jede einzelne Iteration, die wir hier haben. Und das wird uns auch beibringen, wie wir Informationen zwischen verschiedenen Threads weitergeben können , damit all das Zeug irgendwie gleichzeitig ausgeführt werden kann. Das kommen wir im nächsten Video. 7. Queues und Master-Scheduler: In der letzten Lektion haben wir unseren Yahoo Finance-Arbeiter sowie unseren Wiki-Arbeiter eingerichtet , den wir vorher hatten. Und wir scrollen einfach durch alle Symbole und schickten Anfragen und, wissen Sie, haben die Preise, die wir konnten. Aber jetzt werden wir das systematisieren und es ein bisschen schöner machen. Und was wir tun werden, ist, dass es sich um separate Prozesse handelt. Anstatt also durch das Symbol zu scrollen und dann für jedes Symbol direkt einen Thread zu erstellen, werden wir alle diese Entitäten trennen. Also werden wir zuerst alle Symbole durchlaufen. Und dann werden wir einfach, wenn wir ein Symbol bekommen, wir es einfach in etwas setzen, das als Warteschlange bezeichnet wird. Und dann haben wir verschiedene Threads von den Yahoo Finance-Arbeitern, die aus dieser Warteschlange lesen werden. Also haben wir irgendwie diese Zwischensache. Und so ja, wieder, das Ding, das wir benutzen werden, nennt man eine Warteschlange. Und wirklich die Idee, er, Idee hier ist, dass wir Elemente nehmen können und wir sie in das Q setzen können. Und so trennen wir irgendwie, wie schnell oder wie langsam verschiedene Threads laufen. Weil das Q aufbauen kann und wir viele Elemente in setzen können. Und dann können unsere Arbeiter, unsere nachgelagerten Arbeiter. Also diejenigen, die aus dieser Warteschlange nehmen, können einfach aus der Warteschlange auslesen, wann immer sie bereit sind. Auf diese Weise haben wir auch ein wenig von, und wir werden das in einem später sehen. Wir haben mehr Kontrolle darüber, wie viele Eingangsarbeiter wir haben wollen, wenn wir das skalieren können. Aber auch wie viele Leser der Warteschlange mögen, wie viele Verbraucher der Warteschlange wollen wir haben. Wenn wir bemerken, dass sich unsere Warteschlange zu schnell stapelt und sie immer wächst, dann können wir mehr Verbraucher hinzufügen. Und wenn wir bemerken, dass unser Ding oder das q grundsätzlich immer leer ist, dann können wir tatsächlich die Anzahl der Verbraucher senken, weil es uns nicht wirklich einen Vorteil bietet, so viele Arbeiter zu haben. Also, um eine Warteschlange zu implementieren, werden wir die Multiprocessing-Bibliothek verwenden. Und von hier aus werden wir Q importieren, das. Und dann werden wir eine Warteschlange erstellen, die unser Symbol Q sein wird, das eine Instanz von Q wie diese sein wird. Und was wir tun werden, ist, lasst uns das vorerst aussagen. Kommentieren Sie das hier. Wenn wir hier durch die Symbole schrubben, werden wir nur unser Symbol q verwenden und hier werden wir das Symbol setzen, also werden wir es in die Warteschlange einfügen. Jetzt sind Cues threadsicher, was großartig ist, weil das bedeutet, dass wir tatsächlich Threading Steuersystem verwenden können. Alles klar, und so, ja, das ist alles, was wir auf diese Weise tun müssen. Wir setzen Elemente in unsere Warteschlange. Und wenn wir das einfach ausführen und dann können wir einfach die Warteschlange am Ende ausdrucken. Und es gibt tatsächlich eine get-Methode, die wir verwenden können, die nur das nächste Element aus der Warteschlange bekommt. So können wir unsere Hauptfunktion ausführen, nur um die Ergebnisse daraus zu sehen. So sehen wir, dass wir hier eine implementierte Warteschlange oder eine Instanz des Objekts haben. Und mit der get-Methode erhalten wir den ersten Wert aus der Warteschlange, die in diesem Fall das erste Symbol ist. Wir erwarten es. In Ordnung, jetzt, da wir diese Elemente in die Warteschlange stellen, können wir jetzt einen separaten Strom von Prozessen haben, die aus dieser Warteschlange verbrauchen können. Und das ist es, was unsere Yahoo Finance Preisträger im Wesentlichen sein werden. Aber wir werden auch die Dinge hier oben ein bisschen ändern. Und anstatt die Yahoo Finance Preisarbeiter dies direkt tun zu lassen, werden wir das tatsächlich ändern und wir werden einen Scheduler haben , der sich um das Threading kümmern wird. Und dann werden wir unsere Yahoo Finance Preisarbeiter selbst nur die Klasse sein, die die Preisinformationen extrahiert. Aber wird eine andere Klasse Kino verantwortlich für die Multiprocessing-Teil haben. Also nennen wir das den Yahoo Finance Preisplaner. Und das wird eine Instanz des Laufens sein. Und das wird eigentlich keine Unterklasse der Threading-Klasse mehr sein. Also hier wieder, wir werden das initialisieren. Wir werden die übergeordnete Klasse initialisieren. Wir werden auch Keyword-Argumente zulassen. Ups, und übergeben Sie diese hier an die übergeordnete Klasse. Okay, und dann überschreiben wir die Run-Methode. Und hier werden wir nur eine Endlosschleife haben. Und im Grunde, was wir in dieser Endlosschleife tun werden, ist das, was wir gerade aus der Warteschlange lesen werden. Und was wir hier brauchen, ist auch, dass wir eine Eingabe-Warteschlange brauchen, weil wir ein Lesen aus einer Warteschlange brauchen. Also werden wir zur Verfügung stellen, dass als Eingabeargument hier ein Initialisierungsargument hat. Wir werden hier unsere Eingabe-Warteschlange haben. Und dann werden wir unseren nächsten Wert nur autodidaktische Eingabe-Warteschlange haben. Wieder. Jetzt ist dies eine blockierende Operation, was bedeutet, dass sie dies blockieren wird, oder diese Operation wird blockieren, bis wir tatsächlich einen Wert erhalten. Wir kommen später dazu. Aber im Grunde, während diese Schleife läuft, wird es nur versuchen, weiter aus der Warteschlange zu lesen. Und jedes Mal, wenn es einen Wert erhält, wird es die Ausführung fortsetzen. Also auch was wir hier tun wollen, ist, weil wir hier eine Endlosschleife haben , an einem Punkt, an dem wir daraus ausbrechen wollen. Also ein einfacher Weg, dies zu tun, um zu sagen, in Ordnung, wenn wir den w1-Wert senden und wir fertig sind, jetzt wollen wir nur ausbrechen. Abgesehen davon. Wenn wir einen Wert erhalten und dieser Wert nicht fertig ist, gehen wir davon aus, dass es sich um ein Symbol handelt. Und dann wollen wir eine Instanz unseres Yahoo Finance Preisarbeiters haben . Und das Symbol, das wir hier übergeben werden, wird unser Wert sein, weil wir sicherstellen werden, dass unser Upstream Q tatsächlich den Wert hier eingibt. Und dann werden wir auch diese Laufmethode ändern. Und wir werden es stattdessen umbenennen, um zu extrahieren oder Preis für Spark zu erhalten. Wir nennen es einfach einen guten Preis. Ordnung? Also werden wir das nennen, und wir werden Preis sagen. Und hier, anstatt den Preis auszudrucken, Lasst uns voran gehen und den Preis zurückgeben. Also werden wir sagen, unser Preis ist gleich der Verwendung der Instanz unseres Yahoo Finance-Arbeiters hier, wir werden den Preis bekommen und müssen diesen hier nach oben verschieben, den Thread starten. Und dann, wenn wir hier wollen, können wir die Presse für jetzt und später ausdrucken, wir werden das tatsächlich in eine andere Warteschlange stellen, die verantwortlich sein wird, für welche nachgelagerten Arbeiter dort verantwortlich sein wird. in die Datenbank einfügen. Aber im Moment werden wir es nur ausdrucken. Und Yang, wir brauchen den Schlaf hier nicht mehr. Aber was wir tun können, wenn wir wollen, ist, dass wir hier am Ende ein wenig Schlaf hinzufügen können , da wir es nicht wirklich sind, dies ist nicht wie eine API-Anfrage, also erhalten wir keine Informationen von der API in der Header ungefähr wie große Grenzen oder so etwas ist und wie viele Anfragen wir tun können. Also, um nach jeder einzelnen Anfrage respektvoll zu sein, werden wir einfach irgendwo zwischen 01 Sekunden schlafen , nur um den Prozess ein wenig zu verlangsamen. Also wieder, was wir hier haben, ist, dass wir jetzt unsere Scheduler-Klasse haben, die wir irgendwie zu unserer Master-Threading-Klasse bewegen. Und dies wird eine Eingabe-Warteschlange als Eingabe nehmen. Und dann starten wir den Thread. Und dann geht es im Grunde in eine Endlosschleife. Es wird weiter aus der Warteschlange lesen, bis es den Wert liest, an welchem Punkt es ausbrechen wird. Und jedes Mal, wenn es den Wert erhält und dieser Wert nicht getan wird. Es wird eine Instanz der Yahoo Finance Preisarbeiterklasse erstellen. Es wird diesen Wert als Symbol zur Verfügung stellen. Seit der Abfrage oder unter der Annahme, dass das ist, was wir von dieser Klasse hier bekommen. Und dann werden unsere jungen Finanzpreisarbeiter einfach dafür verantwortlich sein , den Preis dort zu extrahieren. Und ja, das war's vorerst. Also lasst uns weitermachen und das hier rüber nehmen. Und wir werden vorher eine Instanz erstellen, so dass, wissen Sie, sobald wir anfangen, Werte bis zur Warteschlange zu setzen, wir tatsächlich anfangen können, sie zu konsumieren. In Ordnung, also erstellen Sie hier eine Instanz unseres Yahoo Finance Preisplans. Nein, Sie müssen sicherstellen, dass wir die Eingabe-Warteschlange geben. Jetzt wird die Eingabe-Warteschlange, die wir verwenden werden, das Symbol Q sein, da es hier lesen sollte. Also, ja, im Moment haben wir nur einen Thread, den wir hier erstellen. Lassen Sie uns einfach eine Liste für diese erstellen, falls Sie mehr haben wollen, die wir später auf Finanzen, Preis, Scheduler, Mieten. Und so. Und dann können wir diese Schleife einfach hier behalten, das brauchen wir nicht mehr. Alles klar, eine Sache, die wir am Ende hier tun müssen, ist, weil wir auf den w1-Wert warten. Sobald wir fertig sind, stellen Sie sicher, dass wir hier fertig sind. So dass unsere Klasse tatsächlich beendet wird, oder dieser Thread tatsächlich ein Ausgang ist. Eine Sache, die wir tun können, anstatt nur eine zu setzen, ist, wenn wir das später ändern wollen, was wir sehr bald werden, wir für Schleifen sagen. Für wie viele Threads wir haben, werden wir einen w1-Wert setzen, um sicherzustellen , dass jede Instanz unseres Threads tatsächlich brechen wird. Denn wenn wir hier nur einen Wert eingeben, weil wir aus dieser Warteschlange konsumieren , wird jeder, jeder Thread nur einen Wert lesen. Und sobald es diesen Wert erreicht, um im Grunde getan. Also, wenn wir mehrere Threads haben und nur einer von ihnen den w1-Wert sieht, dann nehmen wir an, wir haben vier Threads. Einer von ihnen liest fertig als die anderen drei Threads werden nicht ausbrechen, weil die Warteschlange leer ist und sie darauf warten, dass etwas gelesen wird. Und das blockiert nur jede weitere Ausführung für diesen Thread für das gesamte Programm, nur für diesen Thread. Deshalb wollen wir sicherstellen, dass wir hier nur genug getätigte Werte zur Verfügung stellen, um sicherzustellen, dass jede einzelne Instanz der Kehle, die wir haben, tatsächlich ausbricht. Und ja, lassen Sie uns weitermachen und das laufen. Dieser sollte etwas langsamer sein, da wir gerade nur eine Instanz unseres Threads haben. Das ist genau das, was wir hier sehen. Wir extrahieren nur unsere Werte und setzen unsere Werte hier in die Warteschlange. Und wenn ein Wert beginnt, weißt du, ist in dieser Warteschlange , dann beginnt unser Arbeiter hier. Also ist es bereits vorher initialisiert und es beginnt bereits zu laufen. Und sobald wir es initialisieren bei tritt diese Schleife ein, und dann tut es dies. Und jetzt wartet es nur, bis etwas in der Warteschlange steht. Sobald etwas in der Warteschlange ist, wird es davon lesen. Sobald so, sobald das erste Symbol hier gesetzt wird, wird anfangen, von ihm zu lesen. Wenn wir wollen, können wir sehen, dass wir einen Schlaf hinzufügen und sagen wir einfach, schlafen für zehn Sekunden. Und wir können sagen, das erste Symbol einfügen. Also schauen wir uns das einfach an. Also werden wir das erste Symbol einfügen und dann werden wir warten, um ein Symbol eingefügt zu haben. Aber sobald es eingefügt ist, gibt es einen Wert im Q und R Yahoo Finance Preisplaner , der bereits ausgeführt wird, sobald etwas in der Warteschlange ist, dann kann es es hier aus der Warteschlange holen und es kann beginnen, seine Arbeit zu tun. Sobald also etwas in der Warteschlange ist, beginnt es seine Arbeit zu erledigen. Was wirklich schön ist, weil diese Art von macht alle Prozesse unabhängig voneinander. In Ordnung, also können wir das natürlich wegnehmen. Und jetzt, wenn wir das ein bisschen schneller machen wollen, müssen wir nur, wissen Sie, sagen wir, Num, Yahoo Finance, Preisarbeiter. Nehmen wir an, wir wollen für Arbeiter haben. Und wir können sagen, für wie viele Arbeiter sie haben wollen, wissen Sie, wir schaffen nur eine davon. Und so jetzt hätten wir in diesem Fall für Arbeiter, die jeden von ihnen laufen warten, um aus der Warteschlange zu lesen. Und wenn hier etwas in die Warteschlange gestellt wird, fangen sie an, davon zu konsumieren und sie werden anfangen, ihre Arbeit zu machen, wie wir hier sehen können. Und unsere Warteschlangen sind threadsicher, was wirklich schön ist, denn wir müssen uns mit keinem der Probleme befassen, über die wir vorher gesprochen haben. Und okay, jetzt bekommen wir ein paar gute Werte hier, okay, mit denen wir es zu tun haben. Der Preis ist also zu hoch. Eine Sache, die wir hier tun können ist, etwas Formatierung zu machen und dies den Rohpreis zu nennen. Und es sieht so aus, als gäbe es ein Komma für Tausende. Also werden wir das einfach durch eine leere Zeichenfolge wie diese ersetzen. Nur um zu beheben, wo es nicht war, wie diese Formatierung Dinge. Also ja, wir haben jetzt einen wirklich schönen Punkt erreicht , weil wir irgendwie diese Unabhängigkeit zwischen unseren verschiedenen Hinweisen haben . Da gehen wir. So können wir sehen, dass die Tausende auch arbeiten. Wir haben diese Unabhängigkeit zwischen unseren verschiedenen Threads, weil man kann, das ist nicht einmal, ich meine, das wäre Teil unseres Haupt-Threads. Es ist nur, Werte in die Warteschlange zu setzen. Und wann immer etwas hineingesteckt wird, haben wir hier unsere verschiedenen Arbeiter, die bereit und verfügbar sind, um damit zu beginnen, davon zu konsumieren. 8. Einen Postgres: In Ordnung, also jetzt gehen wir weiter und arbeiten an unserem Datenbank-Einfügearbeiter. Also werde ich nur meine lokale Postgres-Datenbank verwenden. Ich benutze hier Datengruppe, aber natürlich können Sie jede Codierungsumgebung verwenden, wissen Sie, Sie genießen die meisten oder Codierung IDE. Ja, wenn Sie nicht super frisch sind, wie Sie Ihre Postgres-Datenbank erstellen, stellen Sie sicher, dass Sie voran gehen und schauen Sie sich den SQL-Kurs an. Aber sonst, ja, drehen Sie einfach einen lokalen Postgres-Server. Und dann werde ich auch hier die Standard-Postgres-Datenbank verwenden. Und wir werden nur eine Tabelle in unserer Postgres-Datenbank erstellen werden nur diese Werte einfügen. Also werde ich sagen, Tabelle erstellen, und wir nennen diese Preise. Und wir werden eine ID-Spalte haben , die Müsli sein wird und wir werden nur unser Primärschlüssel sein. Und dann werden wir auch das Symbol haben, das ein sein wird, nur b, den Text. Und dann werden wir Preis haben, der eine Fließkommazahl sein wird. Und dann haben wir auch die Zeit, oder wir nennen diese Einfügezeit. Wünsche werden nur ein, nun, lasst uns einfach ein Zeitstempel sein. Okay, also ist es eine ziemlich einfache Datenbanktabelle , die wir hier haben, wird nur eine einzelne Tabelle hier mit dem Individuum sein oder eine einzelne Tabelle mit den Preisen hier werden wir unsere ID-Spalte haben, , die nur seriell als unser Primärschlüssel sein wird. Und dann nur ein Symbol sowie der Preis und die Zeit. Oder vielleicht anstelle der Einfügezeit haben wir gerade Zeit extrahiert. Also die Zeit, die wir es von der Website bekommen. Okay, also lassen Sie uns weitermachen und das laufen. Und da gehen wir. Zurück in unser Threading-Verzeichnis hier wurde ein neuer Arbeiter erstellt , der unser Postgres-Arbeiter sein wird. In Ordnung? Und hier werden wir zwei Dinge haben. Wir werden nur unser Postgres-Masterplaner sein , der eine Instanz des Threading-Threads sein wird, wie wir es vorher hatten. Genau wie bei dem Yahoo Finance Preisarbeiter. Und wir werden außer Schlüsselwortargumente sowie eine Eingabe-Warteschlange. Und dann lassen Sie uns einfach die Eltern initialisieren, die Schlüsselwortargumente übergeben. Legen Sie die Eingabe-Warteschlange als die Eingabe-Warteschlange fest, die wir von der Initialisierung nehmen. Und überschreiben Sie dann die Run-Methode. Genau wie wir es für Yahoo Finance Mitarbeiter getan haben. Und wir werden hier noch einmal sagen, wir werden uns unsere Eingabe-Warteschlange ansehen. Und wir werden nur warten, bis ich den nächsten Wert bekomme. Und ohne Wert ist getan, und wir werden aus unserer Schleife brechen. Also, das wird im Grunde die Essenz unseres Gastgebers Chris Master Scheduler sein, genau das, was wir hier für Yahoo Finance Arbeiter getan haben. Und natürlich, nicht zu vergessen, wollen wir sicherstellen, dass wir den Thread T2 starten, sobald wir eine Instanz unserer Klasse initialisieren oder erstellen. Alles klar, jetzt müssen wir die andere Sache tun, die nur unseren tatsächlichen Postgres-Arbeiter behandelt, der dafür verantwortlich ist, die Daten in unsere Datenbank einzufügen. Und dieses in der Initialisierungsmethode. Dies wird das Symbol sowie den Preis als Eingabe nehmen, und vielleicht auch die extrahierte Zeit. Es wird nur all diese Werte als Eingabe nehmen. Und wir können das in ein wenig aufräumen und machen, dass dies eine Art Wörterbuch als Eingabe oder etwas sein kann, aus dem Sie die Werte herausbekommen können. Phrenologe, lass das so, wie es ist. Also werden wir unser Symbol B haben, das Eingabesymbol. Wir werden unseren Preis haben, der Input-Preis, wird haben. Der Extrakt der Zeit. Wenn du hier eine Zeit extrahierst, okay? Und jetzt brauchen wir im Grunde die Methode, die in die Datenbank eingefügt werden wird. Und das wird unsere Einfügung tun. Und in unserer Einfügung hier müssen wir zunächst die Einfügeabfrage erstellen. Und dann müssen wir tun, dass wir die Einfügung durchführen müssen. Also werden wir die Create, Insert-Abfrage eine separate Methode haben. Ich werde nur die Abfrage für uns erstellen, damit wir das zurückbekommen können. Und dann werden wir die Einfügung durchführen. Also, um die Abfrage zu erstellen, werden wir tun, ist, dass wir dies nur mit rohem SQL hier tun. Wir werden sagen, einfügen in Preise, Werte. Und dann werden wir, nun, es gibt verschiedene Möglichkeiten, wie wir das tun können. Einer von ihnen ist, dass wir e, f Formatierung hier verwenden können , um zu sagen, gut, es ist auch hier definieren die Spaltenreihenfolge Interesse sicher zu sein, Preis und extrahierte Zeit. wir sicher, dass das zu unserer Syntax passt. Also setzen Sie dies auf eine neue Linie, nur um es klarer zu machen. Also wieder, der erste Weg, wie wir es tun können, ist die Verwendung der f Strings. So wie das. Nur Art der Formatierung in den Werten direkt. So wie das. Das ist okay. Weil wir das intern machen. Und es gibt keine wie externe Eingabe, aber es ist nicht die beste. Es gibt tatsächlich einen besseren Weg, dass wir dies tun können, was die Textformatierung für uns getan wird. Und wir stellen nur irgendwie wie hier wird das Symbol sein, das später zur Verfügung stellen wird. Hier wird der Preis sein, und hier wird die extrahierte Zeit sein. Und dann brauchen wir auch nicht die f-Saite hier. Und ja, das ist im Grunde die SQL-Abfrage , die wir haben müssen. Es ist nicht viel, aber das ist okay. Und dann werden wir nur diese Abfrage drehen. Also wieder, das erste, was wir hier tun werden, ist dass Einfügeabfrage nur für uns erstellt wird. Und jetzt müssen wir tatsächlich die Datenbank einfügen in die Datenbank einfügen, wir müssen eine Datenbankverbindung einrichten. das zu tun, werden wir eine Bibliothek namens SQL-Alchemie verwenden, die uns nur sehr helfen wird. Was uns nur helfen wird, wie das Einrichten der Datenbankverbindung, Ausführung dieser SQL-Befehle. Und es ist wirklich wie eine allgemeine Bibliothek, die wir verwenden können, um nur eine Verbindung mit Datenbanken herzustellen. Aber ich zeige dir in einer Sekunde wie das Wesentliche. Aber das erste, was wir tun müssen, ist, dass wir es installieren müssen. Also werden wir die SQL-Alchemie wie folgt pip installieren. Und dann in einer Sekunde, dann werden wir auch pip installieren Kuchen P. Und ich hoffe wirklich, ich bin Wirbelsäule richtig. Aber wenn nicht, werde ich es in einer Sekunde nachschlagen. Kreis-Scopy-Binärdatei. Es hat einen Tippfehler. Also lasst uns das ausprobieren. Und es ist groß. Da ist es. Das ist also pip install pi, psi. Denken Sie immer flacher an die Aussprache davon, das heißt, ich kann es nie ausschreiben. Psi Cop G zu binär. Und das wird es uns ermöglichen, die Postgres-Verbindungen aufzubauen. Wir werden also SQL-Alchemie installieren. Wir müssen nicht einmal psycopg2 importieren. Wir werden die Binärversion installieren, weil es manchmal ist, wenn Sie nicht Zelle die Binärversion haben, sie sind wie Probleme mit der Installation. Also einfach immer eine binäre Version installiert, aber das wird uns im Grunde nur den Treiber zur Verfügung stellen, den SQLAlchemy verwenden kann, um tatsächlich eine Verbindung mit der Datenbank herzustellen. Also ja, wie können wir diese Datenbankverbindung einrichten, während wir das tun? So können wir schon hier sehen, ich habe es bereits importiert. Aber wir werden diese Create-Engine-Methode verwenden. Und wir werden einen Motor schaffen. Und die Engine wird es uns ermöglichen, mit unserer Datenbank zu interagieren. Also zuerst müssen wir alle unsere Datenbankparameter abrufen. Wir werden nur unser Postgres-Benutzername sein. Und eine nette Möglichkeit, dies zu tun, ist, dies als Umgebungsvariable zu setzen. Postgres. Benutzer. Dann bekommen wir das Postgres-Passwort, das wir auch Postgres-Passwort benötigen. Und dann brauchen wir auch den Host oder die URL oder wo auch immer sie sich befindet. Es wird also Postgres-Gastgeber sein. Und dann müssen wir auch die Datenbank bekommen, mit der wir eine Verbindung auf dem Postgres-Server herstellen müssen . Das sind also die Verbindungsdetails, die wir brauchen. Und daraus können wir dann eine Verbindungszeichenfolge erstellen , die es uns ermöglicht, sich mit der Datenbank zu verbinden. Also die andere Sache, die ich hier gemacht habe, ist, dass ich das OS-Paket verwendet habe, das es wirklich wichtig für mich ist, nur weil es wirklich schön ist. Aber das erlaubt mir nur, auf Dinge von unserem Betriebssystem zuzugreifen , die speziell hier in die Punkt-Umgebung gehen und mich auf eine Umgebungsvariablen zugreifen können, die ich bekommen kann. Zum Beispiel werde ich hier den Punkt getMethod verwenden. Nun, wenn Sie dies noch nicht mit der dot get-Methode gesehen haben, ist, wenn wir zum Beispiel wie ein Wörterbuch erstellen und wir nur eine Variable hier erstellen. Wenn Sie x dot bekommen, leider bedeuten, Lassen Sie uns diesen x-Punkt wieder umbenennen. A wird den Wert aus diesem Wörterbuch erhalten. Zum Beispiel, wenn Sie x-dot Gatsby machen, die nicht im Wörterbuch enthalten ist, ist es nur irgendwie keines geben. Auf diese Weise, anstatt dies zu tun, was fehlschlagen kann, wenn wir auf Werte zugreifen, die enthalten sind, gibt die GetMethod uns entweder den Wert kippt none, so dass es nicht fehlschlägt. Und dann, was wir tatsächlich tun können, ist, dass wir ein oder hier verwenden können, was passiert, ist zum Beispiel, wenn Sie auf Lager bekommen B oder und dann können wir wie einen Standardwert bereitstellen, den wir verwenden möchten. A sollte ein String und Integer, Integer oder was auch immer sein. So können wir sehen, ob der Wert nicht existiert, erhalten wir den Standardwert. Und wenn es existiert, dann erhalten wir hier den Wert von der GetMethod. Also werden wir sagen, unseren Postgres-Benutzer zu bekommen, oder es wird einfach leer sein. Oder es wird einfach leer sein. Oder es ist nur ein Punkt auf Ihren lokalen Host, oder es wird Postgres sein. Wenn Sie nun Postgres auf einem Mac laufen und es installiert haben, dann ist es sehr wahrscheinlich, dass Ihr lokales Postgres keinen Benutzernamen oder kein Kennwort hat. Aber wenn Sie es unter Windows ausführen, ist es sehr wahrscheinlich, dass Sie einen Benutzernamen und ein Kennwort haben. Der Benutzername wird wahrscheinlich Postgres sein, aber das Passwort ist das, was Sie für Ihre Installation festlegen. Also denken Sie daran, wenn Sie unter Windows sind, wird dies sehr wahrscheinlich plötzlich sein oder Alice wird sich beschweren, dass es eine Verbindung herstellen kann, weil das Passwort keines ist oder es sich nicht authentifizieren konnte oder was auch immer. Aber auf einem Mac müssen Sie keinen Benutzernamen und kein Kennwort festlegen , da Sie es wahrscheinlich nicht festgelegt haben, es sei denn, Sie haben es explizit für Ihre Datenbank festgelegt. Also nochmal, was wir hier tun, ist, dass wir entweder versuchen, diese Werte aus unseren Umgebungsvariablen zu erhalten, oder wenn sie nicht verfügbar sind, wählen wir Standardwerte aus. Und das ist eigentlich wirklich schön, denn dann können wir verschiedene Umgebungen, Umgebungsvariablen für verschiedene Umgebungen einrichten . Sie können beispielsweise über eine Testumgebung, eine Produktionsumgebung oder eine lokale Testumgebung verfügen. Wenn Sie nichts festlegen, dann nehmen wir nur unsere lokalen Testumgebungen. Andernfalls werden alle Variablen benötigt, die wir setzen. Also, jetzt, da wir eine harte Umgebungsvariablen hier haben, können wir unsere Engine erstellen, die uns erlauben wird, eine Datenbank zu verbinden. Wir werden die Crate-Engine-Methode verwenden, die wir von SQLAlchemy erhalten haben. Und wir werden nur f Strings dafür verwenden. Also der erste Teil, es wird nur darauf hinweisen, dass dies eine Postgres-Verbindungen ist. Wir werden PostgressQL tun, Semikolon Schrägstrich. Und dann haben wir unseren Benutzer o. Wir gehen, wir werden wiederverwenden oder Semikolon, Entschuldigung, Doppelpunkt, das Passwort an der Host-Adresse, wie nennen sie das? Ja, Apigee. Die Host-Adresse oder die IP-Adresse oder was auch immer, Schrägstrich, die Datenbank. Dies ist also unsere Verbindungszeichenfolge hier, Benutzername, Passwort, Host, Adresse und die Datenbank, mit der wir eine Verbindung herstellen. Alles klar, jetzt haben wir unser Motorsystem hier. Wir haben unsere SQL-Abfrage, die wir hier erstellt haben. Das Schöne an der Engine ist, dass sie uns ein Mittel zum Erstellen von Datenbankverbindungen bietet . Aber bis wir tatsächlich eine Datenbankverbindung initialisieren, wird keine Verbindung erstellt. Es ist nur, naja, es ist im Grunde nur eine Klasse, die es uns erlaubt, diese Verbindung zu erstellen, sobald wir explizit sagen, dies zu tun. Also jetzt gehen wir voran und führen diese Abfrage. Wir werden Breite sagen. Und dann mit unserem Motor, werden wir uns verbinden. Jetzt gibt es verschiedene Methoden, die wir hier verwenden können. Einer von ihnen ist dot connect, die nur eine Verbindung erstellt. Wir können auch nicht beginnen, was eine Verbindung schafft und eine Transaktion beginnt. Aber wir müssen hier keine Transaktionen verwenden. Also werden wir nur eine Verbindung herstellen. Und wir werden das in unserer con-Variable hier sein. Und Sie werden feststellen, sind alle erinnern sich an die Syntax von auch wie das Öffnen von Dateien aus dem geöffneten Dateinamen und dann wie das Lesen als alles in Datei, das ist genau die gleiche Syntax, die wir hier haben, wo wir eine Datei öffnen, dann können wir etwas tun mit einer Datei. Und sobald wir diese Width-Anweisung verlassen, ist die Datei auch in der Nähe für uns. Also haben wir diesen Context Manager hier, was wirklich schön ist, weil wir die Verbindung damit herstellen. Wir können auf die Verbindung mit diesen Spaltenvariablen zugreifen, wenn ich sie aufrufe. Und sobald wir diesen Breitenblock verlassen, wird die Verbindung automatisch für uns geschlossen, so dass wir uns nicht einmal darum kümmern müssen. So können wir jetzt einfach unsere Verbindung nutzen. Und mit unserer Verbindungsinstanz hier können wir diese Methode nicht ausführen, die uns erlauben wird, diese SQL-Anweisung hier auszuführen. Jetzt gibt es noch eine Sache, die wir tun müssen, das ist, dass wir diese Eingabe bereitstellen müssen, da wir hier nicht als f-Strings zur Verfügung gestellt haben. Also müssen wir es bereitstellen, wenn wir die Einfügung machen. Nun, um Formatierung für diese Syntax bereitzustellen, müssen wir tatsächlich Alaun importieren, eine spezielle Klasse, die es uns ermöglicht, das von SQLAlchemy dot SQL zu tun. Wir werden Text importieren. Und dann werden wir das hier in den Text einpacken. Und dann werden wir hier unseren Beitrag zur Verfügung stellen. Also werden wir unser Symbol haben, das dieses Doppelpunktsymbol oder Symbol ist, wird hier das Symbol sein. Der Preis wird der Preis sein. Und der Extrakt eine Zeit. Es wird die extrahierte Zeit hier sein. In Ordnung, also lasst uns die noch einmal durchgehen. Also haben wir unseren Postgres-Arbeiter, das Symbol, den Preis sowie die extrahierte Zeit als Eingabevariablen einnimmt . Und dann erstellt es auch eine, eine Instanz für eine Datenbankverbindung mit der Postgres-Verbindungsadresse. Und dann werden wir tatsächlich anrufen, wir werden einfügen zwei Datenbank nennen. Und es wird die SQL-Abfrage für uns erstellen. Dann werden wir eine Verbindung mit der Datenbank herstellen. Wir werden also eine Verbindung mit der Datenbank erstellen. Und mit dieser Verbindung werden wir die SQL-Anweisung ausführen, die wir hier erstellt haben. Wir werden diese Textformatierung hier verwenden, weil wir dieses spezielle Format haben das uns im Grunde einen gewissen Schutz vor wie Einspritzsteuer erlaubt. Also nur, dass die Formatierung richtig ist. Und dann können wir die Formatierung hier als nur eine zweite Eingabevariablen und ein sehr einfaches Wörterbuch bereitstellen . Und dann wird es die Werte für uns ausfüllen. Und dann, wenn wir aus dieser Width-Anweisung beenden, wird die Verbindung auch automatisch für uns geschlossen werden , weil wir dies mit Anweisung hier verwenden. Also eine sehr bequeme, Ordnung, also gehen wir zurück zu unserem Master Scheduler. Und was wir hier tun müssen, ist, wenn wir einen Wert aus unserer Eingabe-Warteschlange bekommen, hier werden wir dann eine Instanz unseres Postgres-Arbeiters erstellen, um sicherzustellen, dass das Symbol, den Preis, sowie den Extrakt eine Zeit zur Verfügung zu stellen. Und so werden wir, wir werden das bekommen, na ja, und nehmen wir einfach an, dass es das ist, was wir mit unserem Eingabewert hier bekommen werden. Also unser Eingabewert hier, dass entweder eine Liste sein wird, die so aussieht, oder es wird ein Tupel sein, das so aussieht. So oder so, weil wir die volle Kontrolle darüber haben, gehen wir davon aus, dass wir unsere Daten bekommen. Natürlich, weißt du, wir können das allgemeiner machen und das einfach wie ein Wörterbuch sein. Und dann könnten wir sagen, Symbol ist gleich dem Ventil, wieder Symbol und tun das gleiche für Preis gleich Val dot bekommen, Prius und so weiter. Macht es ein wenig weniger fehleranfällig. Aber, weißt du, das ist jetzt nicht der Zweck. Wir wollen nur, weißt du, wir wollen das nur zum Laufen bringen. Also werden wir nur dafür sorgen, dass es so funktionieren wird. Und dann, sobald wir unsere Profis Caseworker Instanz hier haben, werden wir einfügen in Datenbank aufrufen. Ordnung, das schafft also unseren Postgres-Arbeiter. Jetzt werden wir dies in der nächsten Lektion fortsetzen, da wir hier auch die Eingabe-Warteschlange zur Verfügung stellen müssen. Wir müssen diese Werte da reinschicken. Und auch müssen wir dies in unsere Hauptfunktion hier aufnehmen, denn das wird schon ziemlich lang. Gehen wir voran und halten Sie hier für jetzt und dann weiter in der nächsten Lektion. 9. Integrieren des Postgres Worker: In Ordnung, jetzt, da wir unser Postgres-Port-Mädchen eingerichtet haben, gehen wir weiter und machen das weiter. Integrieren Sie dies in unsere Hauptfunktion, und nehmen Sie einige andere Änderungen in der Zeile vor, um sicherzustellen, dass alles richtig funktioniert. Also zuerst, in der Reihenfolge, Hauptfunktion, werden wir den Postgres-Master Scheduler importieren. Und wir werden eine ähnliche Sache tun, wie wir es für Yahoo Finance Arbeiter hier getan haben. Das und das ist statt Finanzen, es wird unsere Postnoten sein. Und lassen Sie uns den Eingabewürfel und eine Sekunde ändern. Und nur die Namen hier zu aktualisieren. Da gehen wir. Und NAM, Post Grad Worker, wie dies und die Eingabe-Warteschlange. Also, jetzt brauche ich ein neues Q. Und das wird ein VIP-Postgres-Cue wie dieses. In Ordnung, also haben wir hier einen Postgres-Scheduler-Threads, die Anzahl der Podcasts-Arbeiter, nehme an, zwei. Lasst uns vorerst mal sehen, wie die Dinge laufen. Postgres-Scheduler, der Instanz für Postgres Master Scheduler sein wird , der diese Eingabe-Warteschlange hier haben wird. Und Sie behalten diese Bedrohungen im Auge. Also, jetzt, wo wir dieses Postgres-Q haben, müssen wir tatsächlich Werte in sie bringen. Und so werden wir haben, dass dies eine Ausgabe-Warteschlange ist. Top werden wir einem Yahoo Finance Preisplaner zur Verfügung stellen. Nun, es gibt zwei Möglichkeiten, wie wir das machen können. Der erste ist natürlich, dass wir es explizit zu einem Eingabeargument machen können. Oder wir können hier einfach unsere Keyword-Argumente verwenden. Und dann werden wir sagen, okay, also haben wir auf unserer Ausgabe OOP, oder Ausgabe Q, wird es sein? Und dann von unseren Schlüsselwortargumenten, werden wir die Ausgabe Q bekommen. Und wenn das nicht existiert, wird das keine sein. Sonst. Ja, wir werden Werte von hier bekommen. Ordnung, also haben wir während der Run-Methode den Preis hier. Und dann können wir sagen, wenn die Ausgabe Q nicht ist, nicht, dann in unsere Ausgabe Q, wir werden diesen Preis setzen. Ähnlich. Sobald wir hier fertig sind, lassen Sie uns voran und stellen Sie sicher, dass wir auch an unsere nachgelagerten Marker senden. Alles klar, was haben wir gerade gemacht? Nun, wir haben eine Ausgabe-Warteschlange hinzugefügt. Und der Grund, dass wir eine Ausgabe Q brauchen, ist, weil wir jetzt einen Drei-Schritt-Prozess haben. Der erste Schritt besteht darin, alle Symbole zu erhalten, die wir mit unserem Wiki-Worker machen, der kein Thread ist. Es ist nur, naja, es ist Teil des Hauptbegriffs, aber es ist nur ein Arbeiter, der alle Symbole bekommt, die es in das Symbol Q setzen. Das Symbol Q wird dann vom Yahoo Finance Preisplaner gelesen, der Master Scheduler hier. Und jedes Mal, wenn es den Wert bekommt, wird es verarbeiten und den Preis bekommen. Jetzt anstatt den Preis zu drucken, wird es es an die Ausgabe Q hier senden. Und die Ausgabe Q ist, was unser Postgres-Master Scheduler hier als Eingangswarteschlange verbrauchen wird, wie wir hier sehen können. Und schauen wir uns das an. Und wenn wir fertig sind, sobald wir ausbrechen, wollen wir sicherstellen, dass wir auch in die Ausgabe Q setzen und wir fertig sind. Also, was die nachgelagerten Arbeiter sind auch, wissen Sie, dass diese Nachricht an sie weitergegeben wird. Nun ist es wichtig, sich bewusst zu sein, das Format, das wir hier erwarten. Hier, wie wir erwarten, das Symbol, den Preis, sowie die extrahierte Zeit. Also lassen Sie uns tatsächlich festlegen, dass diese die Ausgabewerte sind. Sie müssen also hier das Symbol angeben, das der Wert sein wird, den wir von hier erhalten, der Preis sowie die extrahierte Zeit, die wir einfach in eine ganze Zahl konvertieren lassen. Und das werden wir in Ihre Ausgabe Q setzen. Seitdem erwartet unser Postgres-Worker das Symbol und dann den Preis und dann das extrahierte Zeitsymbol, weil sie das aus der Eingabe-Warteschlange bekommen, die das Symbol Q. Preis. Und dann die extrahierte Zeit hier. Und diese Werte werden wir in unsere Ausgabe Q setzen und dann werden wir diese hier als Eingangswarteschlange in unserem Postgres-Arbeiter lesen. Alles klar, ja, und dann schicken wir den w1-Wert , den wir hier bekommen können. Okay, also gehen wir weiter und lassen Sie uns das testen. Sehen Sie, wie die Dinge laufen, wenn wir etwas verpasst haben. Es wurde ein unerwartetes Schlüsselwortargument ausgegeben Q. Okay? Also eigentlich in diesem Fall sollten wir es explizit definieren, weil wir wie Ausgabeargumente weiterleiten. Und so gibt es uns heraus, wo wir unsere Keyword-Argumente weitergeben. Und es sagt im Grunde, oh, na ja, okay. Die Threading-Klasse, die diese Schlüsselwortargumente verwendet , weiß nicht, was, wie man Ausgabe-Warteschlangen behandelt. Also eigentlich werde ich es explizit definieren , so dass wir es nicht weitergeben, weil es Fehler Downstream verursacht. So wie das. Lass uns weitermachen und das noch einmal ausführen. Sehen Sie, wie die Dinge jetzt laufen. Alles klar, okay, so scheint es die Dinge laufen und wir bekommen die Werte weitergegeben. Bud, wir haben einige Probleme beim Einfügen der Daten in unsere Datenbank. Ordnung? Und das Hauptproblem scheint hier mit unserem Zeitstempel zu sein. Und in diesem Fall beschwert es sich wirklich nur, dass wir hier eine ganze Zahl bereitstellen, aber es erwartet einen Zeitstempel. Also lasst uns einfach weitermachen und hier ein Casting einschließen. Lassen Sie uns dies auf eine neue Zeile setzen, nur um die Formatierung zu erleichtern. Also werden wir diesen Wert als Zeitstempel umwandeln. Wir werden hier Listen mit Casting machen. Lass uns das noch einmal versuchen. Ich bekomme immer noch Probleme. Und mal sehen, welchen Wert wir hier vorbeiziehen. Natürlich verwenden wir die. Lassen Sie uns also anfangen, den Zeitwert zu senden. Hoppla, wir wollen im Grunde wie eine Datetime-Instanz senden, die wir einfügen können. So wie das hier. Und dann erwarte ich nicht, dass wir das brauchen. Und lassen Sie uns einfach voran und stellen Sie sicher, dass dies als eine Zeichenfolge umgewandelt wird, damit wir das String-Format erhalten. Damit der Wert, den wir hier bekommen werden, von so etwas sein wird, was auch immer. Ich finde nur eine Zeit, wie so etwas wie dieses Format. In Ordnung, also werden wir das mit der Datetime-Klasse hier bekommen. Also werden wir ein Datetime-Objekt übergeben, das UTC sein wird. Nun, wenn Sie UTC jetzt anstelle von jetzt verwenden, nur so dass alles standardisiert ist und wir noch die Zeitbibliothek brauchen, um, zum Schlafen hier unten am Ende. Alles klar, lassen Sie uns das noch einmal versuchen. Scheint zu laufen und wir hätten eigentlich keine Druckausgabe, aber lassen Sie uns weiter gehen und unsere Datenbank überprüfen. Hier einen Tisch hochziehen. Oh, da gehen wir. So werden unsere Werte für uns eingefügt, wie wir sehen können, was wirklich großartig ist. Das ist genau das, was wir erwarten. Und ja, also lassen Sie uns im Grunde schnell zusammenfassen, was gerade vor sich geht, weil wir viele verschiedene bewegliche Teile haben. Also das erste, was wir unseren Hauptfaden hier haben. In unserem Hauptthread, wo dann das Erstellen eines Symbols Q sowie eines Postgres q. Dies sind Hinweise, bei denen wir auf die Symbole, die wir von unserem Wiki-Wäscher erhalten, weitergeben werden. Wenn man sich die Wiki-Seite hier anschaut, geht dies durch alle Symbole hier. Alle Symbole hier, und es gibt diese hier in dieses Ausgabesymbol Q weiter. Und dann wird unser Yahoo Finance Preisplaner, von dem wir derzeit vier Instanzen haben, aus dieser Warteschlange lesen. Und dann wird es den Preis bekommen oder es wird versuchen, es zu versuchen, und es wird es an den nachgelagerten Q-Tipp weitergeben, um es zu tun. Und es wird es an die stromabwärts Q weiterleiten, die unser Postgres Q hier sein wird. Und das wird diese Werte annehmen. Es wird von der Postgres Q lesen, die die Ausgabe Q hier ist. Und unser Postgres-Arbeiter wird nur weiter aus dieser Warteschlange lesen. Und jedes Mal, wenn es einen Wert bekommt, ist es, ja, ich werde es in die Datenbank einfügen und wir werden uns den w1-Wert bekommen. Dann wird es hier aus der Schleife ausbrechen. Und wir stellen sicher, dass wir nur, wenn wir den w1-Wert in unserer Eingabe hier bekommen, stellen wir sicher, dass wir das an die Ausgabe Q weitergeben, die Postgres von Sloan lesen wird. Ja, das ist irgendwie das, was wir vor sich haben. Mal sehen, wie viele Datensätze wir jetzt in unserer Datenbank haben. Ein 180. Also erwarten wir es. 550. Und wieder, das läuft ziemlich langsam, nur weil wir sind, wir haben dieses Schlaf-Ding, das hier läuft, um irgendwie zu begrenzen, wie schnell geht. Denn das könnte natürlich viel schneller laufen. Also, um sicherzustellen, dass dies richtig endet, anstatt alle Symbole zu erhalten. Ich werde nur ein Symbol haben oder nicht. Ja, wir haben einen Symbolzähler. Und jedes Mal, wenn wir ein Symbol einfügen, werden wir das um eins erhöhen. Und dann sagen wir, nur um sicherzustellen, dass dies richtig funktioniert. Wenn, oh, auf, wenn wir mindestens fünf Symbole haben, werden wir hier rausbrechen, nur um sicherzustellen, dass wir nicht den ganzen Weg warten müssen , bis wir 550 hier erreichen, nur um zu sehen, ob das richtig funktioniert. Also werden wir aufhören, das erneut ausführen. Und jetzt sollte es viel schneller gehen. Wir sollten fünf Symbole gehen, die in die Datenbank eingefügt werden sollten. Und dann sollte alles verlassen, was es tut. Großartig. Das ist also wichtig für uns, denn wenn es nicht enden würde, bedeutet das, dass unsere Threads irgendwo hängen, dass es irgendwo noch einen aktiven Thread gibt. Und wir können sehen, dass wir das bekommen würden. Wenn wir das nicht getan hätten. Dann würde es unseren Postgres-Arbeitern nie gesagt werden, weißt du, getan und sie würden einfach weitermachen. Eigentlich sieht es so aus, als würden wir uns nicht anschließen, was wir hier sehen. Aber wissen Sie, wir verlassen uns nicht, weil unsere Postgres, Arbeiter in dieser Schleife stecken, die im Grunde davon blockiert wird. Sie warten darauf, den nächsten Wert zu erhalten, aber die Warteschlange ist leer und nichts wird in die Warteschlange gestellt. Also einfach für immer hier stecken, also wird es nicht aufhören. Deshalb ist es wichtig, dass wir diese Werte weitergeben um sicherzustellen, dass Downstream-Cues sich auch bewusst sind, dass, okay, es ist Zeit zu stoppen. also aus diesem heraus herauskommen, gibt es noch eine Sache, die wir tatsächlich tun können, um dies zu verhindern. Also eigentlich, Lassen Sie uns das kommentiert für jetzt und gehen Sie in unsere Postgres-Arbeiter. Und hier werden wir ein Timeout hinzufügen. Und lassen Sie uns das auf 10 Sekunden setzen. Und wir werden sagen, in Ordnung, wenn wir in 10 Sekunden keinen Wert haben, dann wollen wir es verlassen. Also werden wir hier eine try and except Anweisung hinzufügen und die spezielle leere Ausnahme erhalten, die wir von Q erhalten können. Import leere Warteschlange ist wieder eine Standard-Python Bibliothek. So können wir einfach von hier importieren. Und Multi-Processing Q, was wir hier importiert haben, implementiert eigentlich direkt die Queue-Klasse aus der Standard-WarteschlangenPython ibliothek. Also von hier aus können wir die leere Ausnahme bekommen. Also, wenn wir speziell die leere Ausnahme fangen, dann wollen wir nur Q oder Timeout gebrochen und Postgres ausdrucken , Scheduler stoppen. Und dann auch hier wollen wir ausbrechen. Also in diesem Fall sind wir nicht, wir senden das fertige Signal nicht an einen Postgres-Arbeiter. Und so wird es ein bisschen hängen. Und aber es wird hier eine Auszeit haben. Und wir werden tatsächlich in ein wenig sehen, dass die Postgres-Arbeiter sowieso aufhören werden, weil nichts in der Warteschlange steht und die Timeouts erreicht sind. So können wir hier das erste One-Stop-Segment sehen, Stopp. Da gehen wir. Deshalb ist es irgendwie nett, weil er sich irgendwie davor beschützt, ewig zu warten. Aber natürlich müssen Sie sich bewusst sein, denn wenn Sie eine Auszeit in der Zeitüberschreitung hatten, ist nicht groß genug für Werte, um von oben zu bekommen. Sie sind nachgelagerte Arbeiter werden tatsächlich aufhören, bevor sie jemals eine Chance hatten zu arbeiten. Oder wenn es eine Unterbrechung dazwischen gibt, dann, wissen Sie, Ihre nachgelagerten Arbeiter werden aufhören, während das Zeug noch vor sich geht. Du musst also etwas vorsichtig sein. Sie wissen, dass Sie Ihre Auszeit nicht zu kurz, weil es natürlich Probleme verursachen kann. Und so, wissen Sie, Sie wollen sicherstellen, dass Sie idealerweise immer beenden indem Sie eine Art Exit-Befehl senden. Sehen wir uns jetzt Ihren QRS an. Okay, es ist Zeit, hier aufzuhören. Und natürlich haben wir hier die Auszeit und wir können dasselbe tun, denn unsere Yahoo Finance wird hierher gehen. Wir werden sagen, versuchen, einen Wert zu bekommen. Wir bekommen die leere Ausnahme. Wir werden Yahoo drucken. Scheduler. Warteschlange ist leer. Und dann sagen wir, wir hören auf, wir werden ausbrechen. Und wir werden sagen für Q und Port leer. Dies wird nur die Importe hier ein wenig reorganisieren. Dass alle Standardbibliotheken hier ganz oben stehen. Und alle installierten Bibliotheken sind unten. In der Regel. Da gehen wir. Bietet nur ein wenig einfachere Struktur, die wir wissen, dass dies alle Standardwerte sind und diese, die wir installieren mussten. Okay, also und alles, was wir auch hinzugefügt haben, hat hier keine Zeitüberschreitung festgelegt. Also setzen wir hier auch ein Timeout, nur für den Fall. Aber natürlich, wissen Sie, seien Sie vorsichtig, denn Sie können Ihre Arbeiter verlassen lassen, während sie tatsächlich noch arbeiten sollten , weil es eine Art Verzögerung gibt, die vorgelagert ist. Und wir brauchen hier eigentlich keine Keyword-Argumente. Also können wir diese einfach herausnehmen, um hier Aussage zu drucken. In Ordnung, ja, jetzt haben wir unsere Arbeiter auf einen von ihnen , die Symbole von hier bekommen. Für jedes Symbol, das wir bekommen, geben wir es weiter, um die Daten von Yahoo Finance zu erhalten. Und für jeden Preis, den wir bekommen, setzen wir das in ein nachgeschaltetes q, von dem Postgres-Arbeiter dann konsumieren werden. Jetzt sind nur noch ein paar kleine Dinge zu tun, die nur den Join am Ende hier machen werden. Also gehen wir über Postgres, Scheduler-Bedrohungen, und rufen Sie einfach Joins am Ende hier an. Und ich werde tatsächlich die Logik unserer Ausgabe QS hier etwas ändern, weil es möglich ist, dass, wissen Sie, im Moment gehen wir davon aus, dass wir eine Ausgabe Q haben, aber vielleicht wollen wir mehr als eine Ausgabe Q haben. Um das zu berücksichtigen, werde ich das in eine temporäre Variable einlesen. Ich werde sagen, wenn unser temporäres Q nicht viel Liste ist, dann möchte ich nur, dass dies eine Liste ist. Also jetzt unsere Ausgabe QS wird eine Liste sein, die eine sein kann, sie können mehrere sein. Und dann müssen wir das natürlich etwas ändern. Und weil wir hier keine mehr bekommen. Was wir also tun können, ist, dass wir für Ausgabe Q in den Ausgabe-Warteschlangen sagen können. Und dann für jede Ausgabe Q, werden wir auf fertig senden. Und wenn es hier keine Elemente gibt, dann wird das leer sein. Es gibt also keine Ausgabe-Warteschlangen, dann wird dies leer sein. Sonst, weißt du, wenn wir einen haben, dann haben wir einen. Und wenn wir mehr als einen haben, dann haben wir mehr als einen. Und wir können tatsächlich ja. In Ordnung. Also ja, jetzt haben wir das nur ein bisschen schöner gemacht , weil wir das wie eine Eingabeliste bereitstellen können. Und lassen Sie uns das auch tun, obwohl wir nur die spezifische Variable akzeptieren. Dies liefert dies jedoch als Eingabe, als Liste. Können wir also einen nachgeschalteten Q haben? Lassen Sie uns das noch einmal ausführen, um sicherzustellen, dass es funktioniert. Aber auf diese Weise haben wir jetzt ein bisschen mehr Flexibilität, weil sie vielleicht vergessen hat, es hier zu ändern. Oh, da gehen wir. Vier, Ausgang Q und Ausgang QS. Da gehen wir. Okay, jetzt haben wir ein bisschen mehr Flexibilität, weil wir das vielleicht nicht nur in einer Datenbank speichern wollen, aber vielleicht wollen wir das in mehreren Datenbanken speichern. Was wir also tun können, ist, dass wir unseren Hauptarbeiter von Yahoo Finance hier haben können, anstatt nur eine Ausgabe Q zu haben. Es kann mehrere Ausgabe-Warteschlangen und verschiedene nachgelagerte Arbeiter haben. Wir können also sagen, wir haben einen Postgres-Arbeiter. Wir können auch haben, wie ich US-Arbeiter oder MySQL-Arbeiter gelesen habe oder was auch immer andere Datenbanken Sie haben. Jeder von ihnen kann von den verschiedenen Hinweise konsumieren, die wir hier zur Verfügung stellen. Und unser Yahoo Finance Worker wird nur auf jede Ausgabe Q schreiben. Also jede einzelne Ausgabe Q, die wir haben, werden wir diese Werte zu schreiben. Und dann können nachgeschaltete Arbeiter, wissen Sie all diese Dinge nutzen und wir bekommen im Grunde die Preise, aber wir können es wiederverwenden, um es in die verschiedenen Hinweise zu setzen , so dass die verschiedenen Arbeiter von ihnen konsumieren können. Und so gibt uns das mehr Flexibilität, denn, weißt du, es wird nicht immer eins in, eins raus sein. Manchmal wird es keine Ausgabe geben. Manchmal wird es mehrere Ausgänge geben. Und so gibt uns das nur ein bisschen mehr Flexibilität in diesem Sinne. 10. Yaml File: Ordnung, jetzt, da wir dieses Arbeitsprogramm implementiert haben, lassen Sie uns weitermachen und es etwas aufräumen. Machen Sie es ein wenig schöner, einen Überblick zu haben und ihn später erweitern zu können, wenn wir möchten, ohne wirklich immer nur neue Codeausschnitte hinzufügen zu müssen oder kopieren Sie das Einfügen oder Ändern der Logik dort. Stattdessen, was wir tun werden, und wir werden das in einer Art Datei definieren, in der wir ausdrücklich sagen können, dass dies die Hinweise sind, die wir haben, entweder die Arbeiter, die wir haben. Und das wird unser Programm hier definieren. Und was wir tun werden, ist, dass wir eine YAML-Datei schreiben werden. Und das werden wir in dieser Lektion behandeln, die Datei schreiben und wie wir sie lesen können und wirklich, was sie für uns bedeutet. Um dies zu tun, werden wir beginnen und ein neues Verzeichnis hier erstellen. Und ich werde diese Pipelines nennen. Du kannst es nennen, wie immer du willst. Ich werde Pipelines nennen, denn was wir hier in der Pipeline haben, beginnen wir damit, die Rohdaten von der Wikipedia-Website zu beschreiben, sie an sie weiterzugeben, aus dem Yahoo-Zeichen extrahiert zu werden und es dann weiterzugeben auf, um in Postgres hochgeladen zu werden. Das wird also eine Pipeline für uns hier sein. Und so werde ich hier eine neue Datei erstellen. Und das wird unser Wiki sein, Yahoo, Schrott oder Pipeline, und nennen es dot YAML. Warum ML? Jetzt, um diese Datei in Python lesen zu können, und wir werden diese Art von einem Bit nach dem anderen machen. Wir werden auch meine virtuelle Umgebung hier aktivieren. Aber ich werde PIP gehen und stolpern. Pi YAML Drücken Sie hier die Eingabetaste und lassen Sie das installieren. Und das ist irgendwie jetzt und die Bibliothek, die wir brauchten, um das wirklich lesen zu können. Und so in einer Sekunde, wenn wir diese YAML-Datei schreiben, können wir die Tortenbibliothek verwenden, die dann einfach in eine im Grunde wie eine Art verschachtelte Liste oder Wörterbuchstruktur für uns umwandelt , die wir in einer Sekunde sehen werden. Das erste, was wir wollen, wenn wir nur unser Hauptprogramm hier betrachten, ist, wenn wir Warteschlangen haben. Also müssen wir irgendwie die Hinweise definieren, die wir wollen. Und dann haben wir auch Arbeiter. Diese sind irgendwie wie die Essenzen dessen, was wir wollen. Also werde ich hier definieren, und ich werde nur sagen, in Ordnung, das sind die Hinweise, die wir wollen. Und ich werde das nur ein wenig schreiben und dann in einer Sekunde werden wir es lesen und, wissen Sie, wir können ein wenig erkunden, wie sich diese YAML-Datei tatsächlich in eine Python Datenstruktur verwandelt. Also hier drin werde ich einfach die Hinweise auflisten. Der erste, ich werde ihm einen Namen geben. Und das hier wird sein, wenn wir zu unserer Hauptfunktion hier zurückkehren, wird es das Symbol Q sein. Also werde ich dieses Symbol Q nennen, es nennen, was immer Sie wollen. Und ich werde ihm auch eine Beschreibung geben. Nochmals, mach dir jetzt keine Sorgen darüber. Ich werde das in einer Sekunde wiedererlangen. Ich will nur etwas hier drin haben, damit wir es sehen können. Und das wird die enthält Symbole, die von Yahoo Finance verschrottet werden. Und dann wollen wir noch ein Q haben, das unser Postgres-Hochladen sein wird. Und die Beschreibung hier wird sein, enthält Daten, die hochgeladen werden müssen. Postgres. Und dann haben wir auch Arbeiter. Und die Arbeiter. Der erste hier, wenn wir uns das ansehen, wird unser Wiki-Arbeiter sein, oder wir können, ja, okay, Arbeiter ist in Ordnung. Hier können wir eine Beschreibung geben. Dies verschrottet rohe Wikipedia-Seite und zieht Symbole heraus. Und dann wieder, werden wir das irgendwie iterativ durchgehen. Aber ich wollte die Art von Basis wie Standort haben, oder wir finden diesen Arbeiter. Also wird es in Arbeitern Dot Key Worker sein. Und die Klasse, die wir verwenden möchten, wird diese Wiki-Arbeiterklasse sein, die ich hier einfügen werde. Und dann wollten wir auch Eingabe-Warteschlangen finden, et cetera, dass, dass wir in ein bisschen zu bekommen. Aber lasst es uns einfach dabei belassen. Also, jetzt haben wir etwas zu sehen. Und dann lasst uns voran gehen und das laden und sehen, wie diese YAML-Datei tatsächlich in etwas, das in Python verwendet wird, übersetzt wird. Also werde ich Python einfach über mein Terminal hier starten. Und ich werde YAML importieren, was wir jetzt tun können, weil wir PMO zuvor installiert haben. Was ich jetzt tun werde, ist, dass ich mit Offen sagen werde. Rohrleitungen. Und ich werde diesen Namen hier kopieren, weil ich ihn wahrscheinlich falsch buchstabieren werde. Und dann müssen wir den Tippfehler finden. Ich werde es im Lesemodus öffnen. Ich werde sagen, nennen Sie das unsere Infile. Und wieder, lasst uns das einfach durchgehen und dann werden wir irgendwie alles zusammenfassen, was wir getan haben. Wir machen ein bisschen Erforschung, aber wir müssen zuerst eine Art Basis haben. Und so werden unsere YAML-Daten einfach sein, und dann werden wir unsere YAML-Bibliothek verwenden. Wir werden eine sichere Ladung machen. Und wir werden eine hier setzen, unsere bloße Kunstdatei, in der wir sie gelesen haben, um Enter zu drücken. In Ordnung, also haben wir es geladen. Also lassen Sie uns voran und werfen einen Blick auf das. So können wir sehen, ist unsere YAML-Daten tatsächlich, und wenn wir auf seinen Typ schauen, ist ein Wörterbuch. Also der erste Schlüssel, den wir haben, sind die Schlüssel, die wir haben. Wenn wir uns die Schlüssel ansehen, haben wir zwei Schlüssel, Hinweise und Arbeiter, und das ist genau das, was wir hier haben. Das erste ist ein q, und das zweite ist ein Arbeiter. Und Sie können fast jetzt sehen, was wir in Python bekommen, Sie können die Struktur hier erkennen, oder? Also haben wir im Grunde diese Art von vertrautem Wörterbuchformat, wo wir den Namen und dann das Semikolon haben, und dann haben wir die Werte darin enthalten. Nun, was wir hier sehen können, ist innerhalb von Cues, wir haben tatsächlich eine Liste. Also gehen wir weiter und nehmen unsere YAML-Daten. Wir werden uns in Warteschlangen ansehen. Also hier haben wir eine Liste. Und der Grund, dass wir eine Liste bekommen, ist, weil wir tatsächlich diese Bindestriche verwenden , die Listenelemente zeigen. Also in diesem Fall müssen wir Elemente hier auflisten. Aber wenn wir nach innen schauen, sagen wir, das erste Listenelement wird hier wieder sehen wir ein Wörterbuch wie wir hier tun. So können wir sehen, dass wir wie eine sich wiederholende Form von zuerst definieren wir Art von Wörterbuchschlüsseln. Dann im Inneren definieren wir den Inhalt. Und dann innerhalb, in diesem Fall verwenden wir Listenelemente, die durch einen Bindestrich gekennzeichnet sind. Und dann haben wir hier wieder ein Wörterbuch, das wir hier sehen können. Wir haben den Namen, der hier der Name ist, und wir haben die Beschreibung. Nun, wenn ich das schreibe, haben Sie vielleicht gedacht, Oh, Sie verwenden bestimmte Schlüsselwörter, um all diese Dinge anzuzeigen. Ich weiß es nicht. Ich habe mich gerade dafür entschieden, Namensbeschreibung, Standortklasse zu verwenden , weil sie praktisch sind und sie dem Programmierer klar sind, wenn Sie dies lesen, sie sind sehr beschreibend und klar, aber Sie wissen, ist es wirklich egal was verwenden würde. Wir könnten hier wirklich alles verwenden, denn wieder, wir bekommen von hier nur Wörterbücher und Listen, die wir verwenden können. Aber nur um unser Leben leichter zu machen, entweder wenn wir es jetzt schreiben oder wenn wir darauf zurückkommen , wenn wir es anderen Menschen zeigen wollen, wollen wir sicherstellen, dass wir beschreibende Namen verwenden, damit es von klarem, was los ist. Also etwas, das wir auch tatsächlich tun können, was helfen kann, die Syntax ein wenig aufzuklären. Anstatt diese Syntax hier unten zu verwenden, können wir tatsächlich eine Syntax wie diese und das Ergebnis verwenden, aber wir werden bekommen, wird das gleiche sein. Also lasst uns einfach hier rauf gehen und wir laden unsere Daten neu. Und dann schauen wir uns noch einmal unsere YAML-Daten an. Und wir können hier die Werte sehen, die wir hier bekommen, sind, beachten Sie, dass ich einen Tippfehler und eine Beschreibung hier habe. Aber wir können sehen, dass die Werte, die wir hier bekommen, immer noch die gleichen sind, oder? Nichts wird in das exakt gleiche Format geändert ist hier. Jetzt ist dies nur eine andere Art, es darzustellen. Also, wenn Sie möchten, bringt diese Art von fast genau in die Python Struktur zurück , die wir haben, an die wir in Python gewöhnt sind, außer natürlich verwenden wir Anführungszeichen, da wir tatsächlich ein Wörterbuch definieren und ansonsten wir würde Variablennamen referenzieren. Aber sobald Sie sich daran gewöhnt haben, kann dieses Format tatsächlich ein wenig sauberer zu lesen sein als dieses. Deshalb werde ich diese Änderungen rückgängig machen. Und ich werde es irgendwie so haben, wie es vorher war , weil es ein bisschen sauberer zu lesen wird. Aber der andere Weg ist, Ihnen wieder zu zeigen, vielleicht zurück in Dinge wie, wissen Sie, in Python zu übersetzen, damit Sie besser verstehen können, was genau los ist. Aber wir können hier sehen, okay, also haben wir die Hinweise definiert und wieder nennen wir sie Hinweise, weil es für uns praktisch ist, nicht weil es in irgendeiner anderen Weise gebraucht wird. Und wir haben diese Arbeiter wieder hier, weil es für uns bequem ist. Also haben wir unseren Wiki-Arbeiter. Und wieder, hier müssen diese Namen nicht gleich sein. Es ist nur praktisch und beschreibend zu benutzen, aber wir können das etwas ganz anderes nennen. Dieses Jahr ist wichtig, weil wir das später verwenden werden, nicht jetzt, aber später. Wir werden es verwenden, um diese Klasse tatsächlich dynamisch von diesem Speicherort zu laden und zu initialisieren. Also wollen wir sicherstellen, dass dieser Standortpfad und könnte es auch einen pfadbasierten Pfad nennen , was auch immer korrekt ist. Und dann hier wollen wir sicherstellen, dass wir den richtigen Marker wie diesen referenzieren , damit wir ihn tatsächlich initialisieren können. Also haben wir den einen Arbeiter hier. Ich möchte auch Eingabe-Warteschlangen setzen. Nun haben wir in diesem Fall tatsächlich keine Eingabe-Warteschlange. Also werde ich es nicht definieren. Aber vielleicht wollen wir wie Eingabewerte übergeben. Und dies kann zum Beispiel nur eine Liste von URLs sein, die gescrubt werden sollen. Also etwas, das wir tun könnten, ist, dass wir diese URL hier nehmen können, die wir verschrotten wollen, und anstatt sie hart in unseren Wiki-Worker zu codieren, können wir sie hier definieren. Und dann, wenn wir andere Wiki-Seiten haben, die der gleichen Struktur folgen, die uns tatsächlich wiederverwenden oder Arbeiter lassen, oder wir erweitern oder Arbeiter Art in der Lage sein, diese verschiedenen Websites zu akzeptieren. Wir können tatsächlich mehr URLs hier setzen, wenn wir zu diesem Punkt kommen. Oder, weißt du, wenn du jemals solche Daten hast. Aber im Moment bleiben wir nur bei dem, aber, wissen Sie, machen es ein bisschen allgemeiner, damit wir hier alles definieren. Also haben wir unseren ersten Arbeiter. Dann werden wir unseren zweiten Arbeiter schaffen Wenn wir auf unsere Hauptfunktion zurückblicken, haben wir unseren Yahoo Finance-Mitarbeiter. Das hier wird also unser Yahoo Finance Arbeiter sein. Die Beschreibung hier wird gezogen Daten oder zieht Kursdaten für ein bestimmtes Aktiensymbol von Yahoo Finance. Die Lage hier wird Arbeiter dot sein, und ich werde diesen Namen hier kopieren , damit es keine Tippfehler gibt, weil das frustrierend sein wird. Und die Klasse, die wir hier laden wollen, wird unser junger Yahoo Finance Preisplaner sein, nicht die Preisarbeiter werden die gleichen sein, die wir hier benutzen. Das ist also, was wir verwenden wollen. Und hier werden wir eine Eingabe-Warteschlange haben wird nur dies eine singuläre Eingabe q sein. Und das wird eigentlich sein, wir können das einfach direkt als Wörterbuch statt halten. Also unsere Eingabe q hier wird, na ja, die Ausgabe von hier sein. Also lassen Sie uns voran und definieren Ausgabe QS. Dieser hier, wir werden einen Plural haben, falls Sie es an mehrere Hinweise senden wollen. Aber im Moment werden wir es nur an das Symbol Q senden, das wir hier definiert haben. In Ordnung? Und wieder, wir verweisen nur irgendwie auf die Namen hier, weil dies alles nur allgemeine Warteschlangen sind. Und so können wir auf diese verschiedenen Hinweise verweisen. Das sind, wir werden später sehen, wie wir diese verwenden werden. Aber ja, das, mit diesen Namenskonventionen, vor allem für die Q irgendwie lässt uns einfach richtig benennen und eine Referenz alles. Also unsere Eingabe q hier wird unser Symbol Q sein. Und unsere Ausgabe QS hier werden nur unsere Postgres Hochladen Q sein. Nun, der Grund, dass ich mehrere Ausgabe QS haben möchte, ist vielleicht ich will nicht nur diese Informationen an eine Standort in einer Art von Worker Downstream, aber tatsächlich mehrere. Vielleicht möchte ich also, dass mein Wiki-Arbeiter es an den Yahoo Finance-Arbeiter sendet, um die Preisdaten herauszuholen, aber auch an einen anderen Arbeiter senden möchte , der einfach direkt all diese Rohdaten irgendwo speichert und macht nichts anderes damit. Oder vielleicht macht es etwas ganz anderes damit. Auf diese Weise kann ich es an mehrere Standorte senden und verschiedene nachgelagerte Arbeiter können sehen, dass diese von hier gelesen werden. Ihre nachgeschalteten Informationen können auf unterschiedliche Weise verwendet werden. Richtig? Definieren wir unseren letzten Arbeiter. Wenn wir zu unserer Hauptfunktion zurückkehren, wird das unser Gastgeber Chris Arbeiter sein. Also, das hier. Also hier nennen wir das unsere Postgres-Arbeiterbeschreibung. Nehmen Sie Bestandsdaten und speichern Sie in Postgres. Die Lage wird essen. Arbeiter, Dot Postgres Arbeiter. Und die Klasse, die wir verwenden werden, wird wieder der Master-Scheduler sein. Denn das wird derjenige sein, der aus der Warteschlange und allem lesen wird. Genau wie wir es in unserer Hauptfunktion hier tun. Ok? Die Eingabe-Warteschlange. Es wird Postgres Hochladen geben. Und wir werden eigentlich nicht einmal eine Ausgabe-Warteschlange definieren, weil es gibt, Sie diese Daten nicht mehr senden möchten. In Ordnung, das sind also unsere Basisdefinitionen. Jetzt können wir diese YAML-Datei später aktualisieren oder wir können ein wenig ändern, während wir los sind. Wir stellen fest, dass Sie die Dinge vielleicht ein bisschen anders beschreiben wollen. Aber im Moment ist dies eine Art Basisbeschreibung eines Programms, natürlich, Moment tut nichts, weil wir es tatsächlich nutzen müssen, was wir in den kommenden Lektionen tun werden. Aber lassen Sie uns einfach vorgehen und das lesen, damit wir sehen können, was wir haben. Und natürlich, um sicherzustellen, dass es funktioniert. also einen Blick darauf werfen, haben wir die verschiedenen Hinweise und Arbeiter. Und in den Warteschlangen haben wir zwei Warteschlangen, das Symbol Q sowie das Postgres-Hochladen. Und in unseren Arbeitern sehen wir uns das an. In unserem Worker hätten wir mehrere verschiedene und wir haben den Wiki-Worker , der hier auch Eingabewerte hat, können wir sehen, dass sie richtig übertragen wurden. Wir haben unsere Yahoo Finance Arbeiter wird darauf verweisen, dass der junge Freund Preisplaner ist. Und unser Postgres-Arbeiter , der auf den Postgres-Masterplaner verweisen wird. Also, jetzt haben wir irgendwie diese vollständige Pipeline, definieren Sie sie in dieser YAML-Datei. Auch hier haben wir es natürlich noch nicht genutzt. Das werden wir in den nächsten Abschnitten tun. Aber hoffentlich können Sie sehen, dass, wenn wir die allgemeine Beschreibung der Funktionsweise eines Programms übertragen können , anstatt es alles hier zu codieren, um es in dieser YAML-Datei viel konfigurierbarer zu sein. Das bietet uns eine Menge Flexibilität, denn sobald wir unsere Mitarbeiter dynamisch erstellen und sie an jede dieser Warteschlangen senden lassen. Wenn wir eine andere Datenbank speichern irgendwo anders hinzufügen möchten. Später sagen wir alles, was wir auch hier sparen wollen eigentlich nur tun müssen, ist wir zuerst die Klasse dafür schreiben müssen, wie wir es hier getan haben, die sich darum kümmern können. Aber dann sagen wir einfach, wir wollen das speichern, um ich weiß nicht, so etwas wie eine Redis-Datenbank. Also werden wir nur noch eine Warteschlange hinzufügen. Und dann schicken wir es auch hierher. Und dann können wir sagen, oh, ich habe gerade bemerkt, dass hier auch ein Tippfehler ist. Also lasst uns weitermachen und das reparieren. Aber ich meine, wir haben das natürlich nicht geschrieben. Aber das ist irgendwie die Idee. Alles, was wir tun müssen, ist, wenn du gehst, und es wird wieder gewürfelt. Das ist also eine Art Idee, dass wir, sobald wir die Klasse dafür geschrieben haben, anstatt unsere Hauptfunktion ändern zu müssen und alles daran anzupassen. Es ist viel einfacher, als wir einfach die Konfigurationsdateien ändern können. Und tatsächlich können wir mehrere verschiedene Konfigurationsdateien für mehrere verschiedene Pipelines erstellen mehrere verschiedene Konfigurationsdateien für liebevoll laufen wollen, aber der Code wird gleich bleiben. Und es sind nur die verschiedenen Pipelines, die wir zur Verfügung haben. Oder vielleicht möchten Sie zusätzliche Eingabewerte mit dieser Art von Format bereitstellen. Ich hoffe, dass Sie sehen können, dass es viel einfacher wird, zu ändern, manipulieren, hinzuzufügen, zu entfernen oder sogar verschiedene Flows zu haben. Nun, nur in der Lage zu sein, den gleichen Code wiederzuverwenden und alles, was wir wirklich ändern, ist der allgemeine Fluss und die Konfigurationen und so etwas. Also, ja, gehen wir weiter und nehmen das wieder raus, weil das natürlich nicht existiert und wir haben diese Art von Klasse nicht implementiert. Aber ja, nur etwas mehr für ein Beispiel, dass Sie sehen können, wie wir das erweitern können und wie es so vielseitig und nützlich wird. Denn wieder ändern wir diese YAML-Datei hier und wir können tatsächlich mehrere verschiedene YAML Dateien für mehrere verschiedene Pipelines erstellen , die wir ausführen möchten. Unser Code bleibt immer derselbe. 11. Ein Yaml Reader erstellen: Also, jetzt, da wir diese YAML-Datei definiert haben, die eine Pipeline sein wird. Lassen Sie uns eigentlich etwas implementieren, das diese Datei lesen kann oder einfach eine allgemeine Datei genommen wird, von der wir annehmen, dass diese Art von Cube Worker-Struktur hat. Und dann wird es nur die Pipeline für uns behandeln. Weil unser Vicki Arbeiter gerade jetzt auch keine Bedrohung des Selbst ist, sondern einfach wie eine Klasse, die die Arbeit macht und einfach die Werte für uns zurückgibt. Für jetzt. Ich werde dieses hier nur kommentieren. Und wir können das einfach in unserer Hauptfunktion für jetzt und später verlassen, wenn wir wollen, können wir ihren Refactor-Wiki-Arbeiter ändern, um stattdessen wie unsere Yahoo Finance Arbeiter oder unsere Postgres-Arbeiter zu arbeiten, wo wir im Grunde diesen Master haben Scheduler-Thread sowie der Worker selbst, aber kann sich um die Arbeit kümmern, so dass wir diese Werte tatsächlich übergeben und von einem anderen Upstream Q lesen können, in das wir dann diese Werte einspeisen können. Aber jetzt lassen wir das einfach so, wie es ist, und konzentrieren wir uns auf die Implementierung von yeah, Im Grunde alles andere. Also werde ich hier eine neue Datei erstellen. Und ich werde das hier anrufen. Ich nenne diesen einen YAML-Leser. Wir könnten es etwas anderes nennen wie YAML Pipeline ausführen oder was auch immer. Alles klar, und dann hier, jetzt will ich nur zuerst Yaml importieren. Das ist etwas, das wir sicher brauchen werden. Und dann lasst uns weitermachen und einfach eine Klasse definieren und dann den Rest des Zeugs importieren, wie wir es irgendwie brauchen. Das wird also unsere YAML Pipeline sein. Schätze, wir können es gelbe Pipeline-Executer nennen. Und dann gehen wir weiter und führen die Initialisierungsmethode aus, die wir vorerst einfach leer lassen. Sie werden sich bei uns melden. Was sind die anderen Methoden, die wir brauchen? Nun, zuerst einmal brauchen wir etwas, das tatsächlich irgendeine Pipeline verarbeitet, oder? Wir müssen in der Lage sein, die Pipeline zu verarbeiten, die wir hier passieren wollen. Es gibt also zwei Möglichkeiten für uns, Indizes diese Pipeline zu übergeben. Einer von ihnen ist, dass wir es hier haben. So können wir haben, wir kennen den Dateinamen oder das Verzeichnis und fanden ihn hier, dass wir daraus lesen können. Oder wir können den YAML Pipeline Executer tatsächlich mit der Pipeline initialisieren , die wir speziell ausführen wollten. Ich werde das wählen, weil ich denke, es ist ein bisschen schöner zu sagen, dass jede einzelne Klasse, die Sie hier haben, verantwortlich ist, sobald Sie eine Instanz davon haben, die für die Ausführung dieser Pipeline verantwortlich ist. Anstatt ein Pipeline-Executer in der Lage zu sein, irgendwelche Pipelines auszuführen macht es nur ein wenig einfacher, darüber nachzudenken , ob Sie jemals initialisieren oder wenn Sie jemals mehrere Pipelines zum Ausführen haben, können Sie einfach initialisieren verschiedene Pipeline-Executoren und benennen sie entsprechend, Sie eine für jede Pipeline, anstatt nur dieselbe wiederzuverwenden, aber später verschiedene Pipelines übergeben. Auf diese Weise kann es ein bisschen mehr werden. Nicht verwirrend, aber vielleicht etwas kniffliger, es einfach zu folgen, oder es ist nicht so offensichtlich, wie Sie bekommen können, bekommen Sie es, wenn er es mit der Initialisierung getan hat. Also hier werde ich nur sagen, Pipeline-Standort, die drei in ihnen sein wird. Oder der Aufruf von Dateinamen ist, weil es ein Pfad sein wird, der wie Pipelines hier drin sein wird. Also wollen diese Art von nur wie ein allgemeiner Standort sein. Also werden wir dieses Attribut setzen. Pipeline. Die Lage wird gleich diesem Attribut sein, das wir hier gesagt haben. Ich schreibe einen Song. Die verschiedenen Teile unserer Pipeline sind, und wenn wir uns auch unsere Hauptfunktion ansehen, okay, was haben wir falsch gemacht? Muss die Hinweise initialisiert werden. Wie viele, um die Arbeiter zu initialisieren? Und dann müssen wir auf die Hinweise zu schicken. Das erste, was wir natürlich verpasst haben, ist, dass wir diese YAML-Datei auch lesen und verarbeiten müssen, oder vielleicht passiert die Verarbeitung später, aber zuerst müssen wir sie einlesen. Also erste Methode, die wir diese Last-Pipeline haben wollen. Und von hier aus setze ich diese Unterstriche hier ein, nur weil Unterstriche im Allgemeinen bedeuten, dass es wie eine interne Attribute oder Methode für die Klasse ist. Während keine Methoden unterstreichen, welche Art von und von Anfang an verwendet werden. Natürlich können Sie immer noch auf beide in Python zugreifen, dass diese Art von Ihnen anzeigt, dass dies eine Methode ist, die ich intern verwenden möchte , weil ich niemanden über den Code möchte. Ich will nicht wirklich, dass sie Load Pipeline nennen. Und so zeigt diese Art von an, dass dies intern verwendet wird. Ähnlich wird hier der Pipeline-Standort intern verwendet und sollte nicht wirklich durcheinander gebracht werden. Weil, wissen Sie, wir haben die Pipeline-Position aus der Initialisierung definiert. Und so sollten wir natürlich die Pipeline mit der gleichen Datei laden und das sollte wirklich nur einmal passieren. Und das sollte irgendwie vordefiniert und so eingestellt sein. So ja. Also müssen wir hier tun, ist, dass wir unseren Goo-Saft öffnen. So viele Vorschläge. Wir öffnen unsere Datei und welche Variable Sie wollen. Und wir werden unsere YAML-Daten gleich Camel Dot Safe Load Input-Datei hier sein. Da gehen wir. Alles klar, das ist das, was wir in unserer letzten Lektion getan haben, um die YAML-Datei hier zu laden sie in dieses YAML-Datenattribut zu setzen. Also, das ist eigentlich der erste Schritt, den wir unseren Pipeline-Raum bearbeiten wollen. Das erste, was wir tun wollen, ist, dass wir diese Pipeline wirklich laden. Nun, da wir diese YAML-Datei in ein Python Objekt geladen haben, das wir lesen können. Das nächste, was wir tun wollen. Auch, wenn wir unsere Hauptfunktion betrachten, wollen wir unsere qs initialisieren. Ok? Also werden wir eine neue Methode haben. Es wird eingeleitete Leben geben. Und sie sind der Typ hier, Würfel. Und ja, daraus wollen wir nur qs initialisieren, okay, also müssen wir jetzt unsere Hinweise irgendwie verfolgen. Also werde ich in unserer Initialisierung und ein anderes Attribut erstellen , das unser QRS sein wird. Und dann werden wir für den Warteschlangennamen sagen, oder tatsächlich wird es für Q in unseren YAML-Daten sagen. Cuz, also was wir hier tun, ist, dass wir haben, das kommt irgendwie ein anderes Wörterbuch. Seitdem haben wir hier einen Schlüssel , der Cuz ist, wenn Sie sich erinnern, es ist nicht, dann lasst uns schnell, schnell einen Blick darauf werfen. Also werden wir YAML importieren. Und dann lassen Sie uns diesen Namen richtig bekommen. Bestimmter Essay mit offenen Pipelines schräg diesen Server, er würde sagen, Ja, ich werde nicht mit dieser sicheren Ladung ausgehen. Das ist also, was wir hier drin haben werden. Und so in unserem cuz können wir sehen diese Liste hier haben und wir haben die verschiedenen Hinweise mit ihren Namen als pulsive Beschreibungen. Was wir also tun werden, ist, dass wir über diese verschiedenen Hinweise iterieren, die wir wollen. Und für jeden dieser Hinweise werden wir tatsächlich eine Warteschlange erstellen. Wenn wir also zu unserer Hauptfunktion zurückkehren, werden wir das im Grunde tun. Und um dieses Q zu erhalten, müssen wir diesen Cue aus Multiprocessing importieren. Also machen wir es so. Und dann für jede Warteschlange, die wir haben, werden wir sagen, oder wir können den Namen der Warteschlange bekommen, wenn wir wollen, was Q2 sein wird. Name. Immer zu sagen, Schleifen sind unser spezifischer Warteschlangenname in unserem Cuz Wörterbuch hier wird nur eine erste Listenversion der Warteschlangenklasse von Multiprocessing sein. Also machen wir das Gleiche hier. Aber anstatt diese Hinweise so zu definieren, ist im Grunde haben wir ein Objekt oder ein Wörterbuch, das so aussehen wird. Natürlich wissen Sie, dass die Namen, die wir verwenden, ein bisschen anders sind. Aber das ist irgendwie die Idee, was wir tun. Und natürlich haben wir die Freiheit, das zu ändern, denn wir können, wenn wir hier mehr Hinweise hinzufügen, dann wird sich das nur darum kümmern. Aber das ist wirklich das Format, das wir hier bekommen. Und anstatt zu verwenden, und ich werde Sie in einer Sekunde sehen, anstatt auf diese Variable zu verweisen, die das Q enthält, können wir dann erst später diese spezifische Warteschlange durch den Zugriff auf die Wörterbuchkomponente bevorzugen. Also machen wir immer noch das Gleiche, aber auf diese Weise erlaubt es uns, zunächst einmal unsere verschiedenen Hinweise zu unterscheiden , weil wir die verschiedenen Namen haben, die ihnen zugeordnet sind. Und es ermöglicht uns auch, sie ein wenig einfacher dynamisch zu skalieren, weil wir ein Objekt haben , das eine 0 undefined halten kann. Während wir diese Code-Anzahl der Hinweise schreiben, die nach Bedarf nach oben oder unten gehen können. Aber ja, im Grunde, wissen Sie, es ist nicht wirklich etwas anderes, um sie in eine, eine eindeutige Variable zu setzen. Aber wir greifen nicht direkt über die Variable auf sie zu, sondern über einen Schlüssel, der in einem Wörterbuch enthalten ist. Das machen wir also hier. Und natürlich wollen wir das tun. Das nächste, was wir tun wollen, ist natürlich, die Hinweise zu initialisieren. In Ordnung, also haben wir unsere YAML-Datei geladen und wir haben uns um diesen Teil hier gekümmert. Lassen Sie uns jetzt voran gehen und kümmern uns um die Initialisierung unserer Arbeiter. So. Das wird unsere nächste Methode sein. Wir werden die Arbeiter initialisieren. Also sagen wir für Arbeiter in Selbstpunkt-YAML-Daten. Und dieses Mal werden wir diese Arbeiter so durchlaufen. Und jetzt wollen wir, nun, zuallererst, wir wollen jeden dieser Arbeiter im Auge behalten. Wir wollen also wissen, welche Arbeiter wir tatsächlich zur Verfügung haben oder welche Arbeiter derzeit arbeiten? Sie werden also unsere verschiedenen Arbeiter hier im Auge behalten, so. Und dann, okay, jetzt sind wir zu einem kleinen interessanten Problem gekommen , weil wir die Klasse sowie den Ort übergeben, wo wir diese Klasse finden können. Aber eigentlich ist dies nur ein Name, wie wir das nicht einfach initialisieren können. Während wir es in unserer Hauptfunktion speziell importiert haben. Also, wie können wir das tun? Nun, es gibt eine coole Bibliothek, die wir verwenden können, die Importlippe genannt wird, was mag, lässt uns uns darum kümmern. Nun, eine andere Sache, die Sie auch hier bemerken, schnell darauf hinweisen , sind alle Bibliotheken , die standardmäßig installiert sind, ganz oben. Und wenn wir dann zu Bibliotheken kommen, die pip installieren und von einer externen Quelle installieren, werden wir durch eine neue Zeile getrennt werden, und diese werden gruppiert werden. Und dann können wir in der Hauptfunktion sehen, dass wir das Gleiche hier gemacht haben. Das ist also eine interne kommt mit Python. Dann haben wir eine neue Zeile, diese Bibliothek und alles andere, was pip install wäre, wird hier gehen. Und dann haben wir eine neue Linie. Und das sind alle unsere benutzerdefinierten Codestücke , die in unserem Repository selbst hier enthalten sind. Auf diese Weise, wissen Sie, sind wir irgendwie in der Lage, die verschiedenen Lokalisierungsschießerungen einfach ein bisschen einfacher zu trennen und es ist ein bisschen einfacher, klar zu machen, wie was zu was gehört. Auch hier ist das eher eine visuelle Sache. Natürlich alles, was nötig ist. Es macht es nur ein bisschen sauberer. Ich wollte nur darauf hinweisen, falls Sie sich fragen, warum ich das tue. Also haben wir diese wichtige Lib-Sache. Also natürlich brauchen wir die Arbeiterklasse, die wir tatsächlich initialisieren können. Also wollen wir in der Lage sein, diese allgemeine Arbeiterklasse zu lesen , damit wir so etwas tun können. Aber natürlich wissen wir nicht, welche Arbeiter wir bekommen werden, weil diese Pipeline wirklich definiert werden kann. Aber, richtig? Als wäre das das Tolle. Aber natürlich, 0 bemerkte linken Punkt in der letzten Zeit. Das ist das Tolle. Aber natürlich müssen wir auch in der Lage sein, damit richtig umzugehen. Um das zu tun, werden wir die Importgliedmaße verwenden oder tatsächlich, wenn wir das erste Attribut verwenden. Und ich erkläre es, lasst uns einfach das Ganze ausschreiben und dann erkläre ich das Ganze hier in einer Sekunde. Und wir werden das lib dot Importmodul importieren. Und das Modul, das wir importieren werden, wird der Workerstandort sein. Also werden wir auf den spezifischen Worker zugreifen und wir werden auf seinen spezifischen Standort zugreifen. Und dann das Attribut, auf das wir zugreifen möchten. Und nochmal, schreiben wir das einfach aus und dann gehen wir noch einmal vorbei. Es wird die Arbeiterklasse geben. Ok. Also, was haben wir gerade gemacht? Werfen wir einen Blick auf unsere Arbeiter. Werfen wir einen Blick auf unseren ersten Arbeiter hier. Also wirklich, wissen Sie, natürlich, wenn wir über diese Arbeiter schleifen, dann werden wir jedes dieser Elemente hier eins nach dem anderen bekommen. Also haben wir den Namen, et cetera, et cetera. Im Moment schauen wir uns den Standort an. Das hier. Das gibt uns also dieses Ding hier, richtig? Dieser Weg Arbeiter dot yahoo Finanzarbeiter, Arbeiter dot yahoo Finanzarbeiter. Das Gleiche wie wir hier gemacht haben. Arbeiter dot yahoo Finanzarbeiter. Ok? Unsere Importschleife wird also dieses Modul so importieren. Also im Grunde wird es so etwas wie Import tun. Und dann wird es nur importieren, importieren. Grundsätzlich erlaubt es uns, dies zu tun. Weil wir nicht nur dieses Modul wollen, sondern vielmehr eine bestimmte Klasse daraus bekommen wollen. Wir müssen ein bestimmtes Attribut aus dieser Klasse bekommen. Nun, dies ist eine interne Python Methode, die uns im Grunde auf Attribute zugreifen lässt. Es funktioniert tatsächlich auf die gleiche Weise. Wenn wir eine bestimmte definierte Klasse hätten, könnten wir unsere Klasse hier nehmen und, sagen wir, wir wollten es tun. Wir haben unseren Yahoo Finance Zeitplan. Ich betrachte und werfe einen Blick in das. Also hier haben wir die Eingabe-Warteschlangen. Also etwas, das wir tun könnten, ist, dass wir sagen können wie Get Attribut hier, und dann haben wir die Eingabe-Warteschlangen. Und so im Grunde ist dies eine Art Möglichkeit für uns, Attribute aus Klassen oder in diesem Fall auch aus Modulen zu nehmen . Denn so etwas zu tun funktioniert nicht wirklich für Klassen und Werke oder Wörterbücher, aber es funktioniert nicht für Klassen, die wir tun müssen, ist Zugriff darauf so, richtig? Aber was, wenn wir dynamisch auf eine Variable zugreifen wollen? Dann können wir nicht einfach so, dass es keinen guten Weg gibt dass wir diese Syntax haben können, wenn dies dynamisch sein soll. Die Art und Weise, wie wir das tun können, besteht darin, diese get-Attribute-Methode zu verwenden. Und dies lässt uns dynamisch das Attribut definieren, das wir von dieser Klasse wie folgt nehmen möchten. So ähnlich können wir die gleiche Dicke verwenden, aber es funktioniert auch auf diesem Importmodul hier. Also importieren wir es und daraus extrahieren wir diese Arbeiterklasse. Also im Grunde ist dieses Ding hier das Gleiche wie das hier, außer dass wir speziell bereits sind, wissen Sie, wir haben diese Klasse, die wir jetzt nehmen. Und wir haben es speziell in dieser Arbeiterklasse Variable hier, so dass wir es verwenden können und wir es initialisieren können. Also natürlich müssen wir diese tun, denn wieder, das kann alles nach Belieben definiert werden. Und so müssen wir in der Lage sein, die Klasse tatsächlich zu importieren und zu verwenden oder sie zu initialisieren und zu verwenden, ohne zu wissen, welche Klasse das sein wird. Wir müssen, solange wir dieses Format der Standortklasse haben, wissen Sie, solange das befolgt wird, müssen wir in der Lage sein, das zu importieren und zu initialisieren. In Ordnung, also haben wir unsere Arbeiterklasse, aber wir brauchen auch einige andere Eigenschaften, die damit verbunden sind. So wichtige Dinge, wenn wir uns unsere beiden Arbeiter hier betrachten brauchen wir die Eingabe q und wir brauchen die Ausgabe QS. Wenn wir unseren Postgres-Worker hier betrachten, brauchen wir nur die Eingabe-Warteschlange. Ok? Also werden wir nur die Eingabe-Warteschlange lesen. Und das ist dieses Attribut hier, das wir mit Arbeitern definiert haben. Also sagen wir unsere Arbeiter. Und hier werden wir nicht nur versuchen , auf das Attribut direkt so zuzugreifen. Denn in einigen Fällen, zum Beispiel, wenn wir dies definiert haben, würde dies nicht funktionieren, weil unsere Eingabe-Warteschlangen hier tatsächlich nicht definiert sind. Also, um gegen so etwas sicher zu sein, werden wir tatsächlich eine Methode dot get verwenden. Ich möchte dir das sehr schnell zeigen. Also, wenn wir ein Wörterbuch haben, wie dieses, sehr einfaches Wörterbuch, wenn Sie x Punkt bekommen ein, wir den Wert des Schlüssels a erhalten , der Karten hier zu sein. Aber wenn Sie x dot sagen, eine oder die Zeichenfolge 1. Das ist also auf der Suche nach dem Schlüssel. Dieser Wert ist nicht hier drin, also werden wir keinen bekommen. Auf diese Weise, anstatt dies fehlschlägt, wird es entweder den Wert hier erhalten, wenn er existiert oder nicht existiert, wird er keinen bekommen. Ok? So können wir, wissen Sie, wir werden sicher sein, dass wir hier nicht scheitern. Wir wollen auch die Ausgabe QS. Und von hier aus werden wir einfach dieses Format verwenden. Es wird unser Ausgang QS hier sein. Ok? Und mal sehen, brauchen wir noch etwas? Wir brauchen also unsere Eingangswerte und unser oberes Cubed. In Ordnung, also haben wir das drin. Aber derzeit ist unsere Eingabe-Warteschlange hier, es wird eigentlich nur ein Name. Es ist nicht die Warteschlange selbst. Also müssen wir diese Hinweise bekommen und dann können wir sie an unsere Arbeiter weitergeben. Also werden wir zu einer Zeit sitzen, wir werden eine neue Variable erstellen, die unsere Initialisierungsparameter sein wird. Und hier werden wir die Eingabe-Warteschlange übergeben, die wir definieren werden. Und wir werden uns auch vorerst nur die Ausgabe-Warteschlangen haben, die auch in nur einer Sekunde definieren werden. In Ordnung, also hier müssen wir tatsächlich eine Instanz der Süßen wie diese übergeben, richtig? Wir können den Namen nicht einfach weitergeben. Das, weil es nur ein Name ist, ist nicht hilfreich. Dafür haben wir hier unsere Hinweise. Was wir also tun wollen, ist, dass wir diese Eingabe-Warteschlange hier bekommen wollen. Wir wollen es holen. Wir wollen die tatsächliche Warteschlangeninstanz erhalten. Also werden wir sagen, self.users dot input, oops, und setzen QM. Wenn Sie q setzen ist nicht keine. Keiner. Wie haben wir das definiert? Oh, ja, natürlich brauchen wir das Komma danach. Es gibt also nur eine Kurzschrift, wenn else Aussage , die wir in einer Zeile schreiben können, so dass wir es nicht über mehrere Zeilen schreiben müssen. Mischen Sie ein wenig einfacher, dass auf welchen Zeilen haben, können wir all diese Logik hier direkt haben. Wenn wir also eine Eingabe-Warteschlange haben, dann nehmen wir die tatsächliche Instanz, die wir hier definiert haben , und verwenden, was Q damit verbunden ist. Sonst wird das einfach keine sein. Und hier, was wir tun wollen. Ist eine ähnliche Sache, was sein wird, wollen wir. Nun, hier müssen wir vorsichtig sein, weil wir mehrere Ausgabe QS haben können, oder? Also wollen wir das mehr so machen, als ob wir dies zu einer Liste machen wollen. Jemand antwortet, um hier zu sagen, aus Punkt-Punkt-Punkt-Ausgang Q für Ausgabe Q. Und Cues. Wenn keine, ist das natürlich ein bisschen lang. Werde ich die empfohlene Anzahl von Zeilen durchlaufen? Wir können dies über 2 Ionen teilen, indem wir hier nur einen Rückwärtsschrägstrich setzen , der uns erlaubt, dies auf zwei Zeilen zu teilen. Okay, jetzt haben wir unsere Initialisierungsparameter. Wieder, was dies tut, ist es uns erlaubt, eine Anweisung über mehrere Zeilen zu brechen, ohne die Logik zu brechen. Denn wenn wir das tun, oder die Logik wäre kaputt, oder? Wir haben nur diese Liste hier. Und dann die nächste Zeile würden wir die Anweisung ausführen. Es wird aus diesem rückwärtigen Schrägstrich Jahr sein. Es verbindet diese Logik tatsächlich zusammen und sagt im Grunde, dass diese Logik direkt in der nächsten Zeile weitergeht. Und auf diese Weise müssen wir uns nicht mit diesem überfließenden Text auseinandersetzen. In Ordnung, also haben wir Initialisierungsparameter-Zelle unserer Workerinstanzen hier. Also lasst uns eigentlich weitermachen und unsere Arbeiter initialisieren. Also vor allem möchte ich nur, um sie zu bekommen oder könnte natürlich den Eigennamen nennen. Es wird den Namen extrahieren. Also für jeden Workernamen, für jetzt werde ich nur eine leere Liste dafür erstellen und dann werden wir die verschiedenen Arbeitergründe anhängen. Also vorerst werde ich sagen, Autodidakt Makler, die Arbeiter namens dot anhängen und diese Arbeiterklasse hier haben. Und wir werden ihm die Initialisierungsparameter übergeben. Das erlaubt uns also zu tun, ist es braucht dieses Wörterbuch und es verwandelt im Grunde jedes Wörterbuch hier in ein Schlüsselwert-Paar, das wir es übergeben können. Also, was in diesem Fall passieren würde, ist das gleiche wie wenn unsere Eingabe q hier keine Schleife wie folgt ist. Und das wäre zum Beispiel Autodidakt, wenn wir nehmen, naja, lasst uns das Beispiel für den jungen Finanzarbeiter nehmen. Und ich schätze nur hier. Und dann gehen wir über, was los ist. Also dieser Stern, Stern entpackt im Grunde dieses Wörterbuch und für jeden Schlüssel hier drin, hat den Schlüssel hier ist dies, und dann ordnet es zu einem bestimmten Wert im Wörterbuch wie diesem. Und es tut dies dynamisch. Wenn Sie also hier weitere Parameter hinzufügen, dann werden alle diese, wissen Sie, jeder von ihnen wird hier in einer Schlüsselwertpaarzuordnung definiert. Das ist also wirklich schön, weil es uns erlaubt, unsere Initialisierungsparameter zu entpacken und sie einzeln zu übergeben, wie Schlüsselwertpaare hier drin, so dass wir spezifisch so definieren können, dass sie ihre Ausgabe-Warteschlangen sehr eigenartig sind, Natürlich, damit dies funktioniert, müssen wir sicherstellen, dass die hier benannt sind, Eingabe q und q also wird dies bereits ein Problem sein, weil ich diese Ausgabe-Warteschlangen aufgerufen habe, aber das wird hier Ausgabe Cubed genannt, also dass es es so schaffen wird. Ein weiteres Problem ist natürlich, wenn wir hier Parameter bereitstellen, die nicht existieren. Zum Beispiel haben wir in diesem Fall tatsächlich beide Eingaben hier. Wir haben kein oberes Q. Also wirklich, wenn wir das hier haben, dann würde es sich beschweren, weil wir Ausgabe Q als Initialisierungsparameter übergeben. Aber es existiert nicht im Postgres-Arbeiter. Aber das ist, wo dieser Stern, Star k funktioniert. Oder Schlüsselwortargumente kommen in. Grundsätzlich ermöglicht es uns, einen E Satz von Schlüsselwortargumenten zu übergeben. Also alles, was mit dem Schlüsselwort definiert und gleich etwas gesetzt wird, ohne sich wirklich Sorgen machen zu müssen , wissen Sie, wie die Auswirkungen. Es braucht es nur irgendwie und dann können wir damit machen, was wir wollen, wenn wir es benutzen wollen. In diesem Fall geben wir es einfach an den Thread an die übergeordnete Klasse weiter. Aber wir könnten das auch ganz ignorieren und nichts damit machen. Hallo. Das ist eine wirklich schöne Art zu tun, weil wir einfach dieses Wörterbuch auspacken und sofort, wissen Sie, übergeben es hier. Und ja, also haben wir fast die Logik, die wir hier haben. Es fehlen noch ein paar Dinge. Zum Beispiel definieren wir hier die Anzahl der Arbeitskräfte, die wir derzeit nicht haben. Das ist eine einfache Lösung für uns, weil wir einfach hier reingehen können. Und wir können sagen, zum Beispiel, Instanzen. Nehmen wir an, wir wollen Form. Und ich nehme das Gleiche und lege das hier hin. Das muss nicht die gleiche Reihenfolge sein. Auch hier bekommen wir ein Wörterbuch-Mapping. Es ist nur eine günstige Zeit, um die gleiche Reihenfolge zu sein. Und hier können wir sagen, oder sagen wir, wir wollen viele Postgres-Arbeiter, aber wir wollen nicht so viele Wäscher. Jetzt können wir sagen, dass die Anzahl der Instanzen, die wir wollen, nur die Instanzen Attribute von hier erhalten, wie diese, und dann eher nur initialisieren, wenn wir sagen, ich im Bereich der Anzahl der Instanzen. Und wir wollen Domini-Arbeiter schaffen. Hier. Eigentlich wäre es wahrscheinlich besser für uns, so etwas zu tun. Und wir können tatsächlich auch tun, ist ein Standard- oder ein Fallback-Parameter. Also in diesem Fall, wenn wir zu diesem x Punkt Punkt a zurückkehren, erhalten wir den Wert b, der dem k hier zugeordnet ist. Wenn wir x Punkt Punkt tun wollte existieren. Aber wenn wir das tun, bedeutet das, wenn es nicht existiert, dann sind wir zurück zu diesem. Wenn also aus irgendeinem Grund die Instanzen, die es nicht definiert ist, wissen wir, dass wir dafür arbeiten wollen, weil es in der Pipeline ist. Also werden wir nur einen benutzen. Andernfalls, wenn die Instanzen Artefakt und wir werden das verwenden. Auf diese Weise können wir jetzt dynamisch erhöhen, wenn wir wollen oder verringern, wann immer wir die Zahl der Arbeiter hier drin wollen, und wir werden einfach so viele Arbeiter schaffen. Und dann ist das letzte, was wir tun wollen, natürlich wollen wir diese Methode Selbstpunkt-Initialisierung von Arbeitern nennen. Und dann wollen wir auch in der Lage sein, den Arbeitern beizutreten, wie wir es hier haben. So Arbeiter und wir sagten bereits für Arbeiter in, Arbeiter werden für Warping Namen und Arbeiter sagen und dann werden wir für Arbeiter Thread sagen. Also denken Sie daran, wir haben ein, dies ist ein Wörterbuch und die jeder Schlüssel hier ist der Name des Arbeiters. Und dann mit jedem Wert werden wir eine Liste haben. Und jede dieser Listen wird eine Arbeiterklasse sein. Jeder von ihnen wird also ein laufender Thread sein. Also wollen wir über jeden Thread schleifen. Und dann würden wir hier den Punkt Join so nennen. Ordnung, also wird das die Klasse sein. Und wir werden hier vorerst anhalten, weil wir offensichtlich sind, dass diese Klasse noch überall implementiert ist, aber das wird irgendwie sein, das bildet die Grundlage ihrer Klasse, die uns erlaubt, all das zu tun. Also die folgenden Lektionen werden wir diese Klasse implementieren und sie irgendwie in unsere Hauptfunktion und, Sie wissen schon, Funktionalität dort drüben zu verschieben . Wir werden natürlich jedes Debugging durchführen, weil wir diese Klasse überhaupt nicht testen konnten, richtig, jetzt wurde sie irgendwie so geschrieben. Es ist also wahrscheinlich, dass es hier einige Fehler gibt, die wir beheben müssen. Manche machen das auch und übernehmen das dann irgendwie. Und vielleicht ändern Sie dann auch eine Funktionalität ein wenig , so dass wir tatsächlich unseren Wiki-Worker hier auch etwas sein können, das wir definieren können, wie spezifisch wir vielleicht mehrere URLs übergeben können. Ja, aber ja, ich schätze, wir machen das in den folgenden Lektionen, da du uns hier nicht mehr zu lange rausschleppen willst. 12. Unser Wiki verbessern: In Ordnung, jetzt, wo wir diesen YAML haben, gehen wir zu finden. Lassen Sie uns eigentlich voran und implementieren dies in unsere Hauptklasse, weil wir gerade jetzt auf unserer Hauptfunktion sind, weil wir gerade diese Kosten in Ordnung haben, aber wir machen nicht wirklich viel damit. Und es ist noch nicht perfekt, wie wir in einer Sekunde sehen werden. Aber wir werden von M Strenge sagen, wir werden den YAML Pipeline Executer importieren. Ordnung, also werden wir unseren YAML Pipeline Executer gleich sein lassen. Und jetzt müssen wir den Pipeline-Standort definieren. Also wird unser Pipeline-Standort von jetzt an Pipelines Slash Wiki sein, Yahoos Kupfer-Pipeline Punkt YAML. Jetzt ist das hart genug codiert. Idealerweise wird es dies in Umgebungsvariablen verschieben, aber wir werden das später tun. Lasst uns dieses Zeug vorerst zum Laufen bringen. Okay, das brauchen wir also nicht mehr, weil wir unseren YAML Pipeline Executor oder Wiki-Arbeiter haben . Interessant, denn das brauchen wir noch. Das brauchen wir nicht mehr. Und das brauchen wir auch nicht mehr. Also müssen wir unsere Verarbeitungs-Pipeline ein wenig ändern, weil wir es nicht können, werden wir in einer Sekunde sehen, aber wir können den Arbeitern noch nicht beitreten. Denn im Moment gibt es so etwas zufälliges. Nicht zufällig, aber als wäre es ein bisschen immer noch nicht perfekt, weil wir einige Sachen in der YAML haben und sie und einige Sachen ausführen, wie wir in einer Sekunde noch ohne sie sehen werden. Also, wenn wir hier nur Prozess-Pipeline aufrufen, werden wir die Pipeline laden. Wir werden einen QRS und Arbeiter initialisieren. Wir wollen uns nicht anschließen, denn wenn wir das tun, dann, wissen Sie, ich bin im Grunde alle Arbeiter waren irgendwie fertig und dann haben wir noch nichts eingesteckt, aber wir können noch nichts hineinsetzen, weil die Q's erst initialisiert werden , wenn wir initialisieren Sie hier tatsächlich die Warteschlange und den Prozess-Pipeline-Schritt. Also leider, vorerst, werden wir das später beheben, aber jetzt müssen wir dieses Joint hier drüben abschalten und wir müssen es später manuell anrufen. Wir sind nicht manuell, wir rufen es einfach später an. Also haben wir unser Symbol Q. Jetzt, das Q, das wir wollen. Moment werde ich sie nur benutzen. Harter codierter Wert wird dieses Symbol Q hier sein. Und natürlich, jetzt wollen wir das alles aus dieser YAML Pipeline machen, denke ich hier. Also, aber jetzt lassen Sie uns einfach die Funktionalität testen. Du wirst also in unseren YAML-Pipeline-Executer gehen. Wir werden tatsächlich auf dieses Attribut zugreifen. Und hier werden wir auf die zugreifen, das Symbol Q, weil das ist, wo es geschrieben werden muss. Das ist also der Schlüssel, den wir natürlich in eine nicht-ideale Syntax schreiben möchten . Aber weil unser Wiki-Worker eigentlich nicht die Pipeline definiert ist und innerhalb des Ureters es irgendwie so machen muss. Ordnung. Anschließend ist der Druck fertig. So müssen wir das momentan auch noch tun. Ähm, so für den Moment, wir, weil wir jetzt wie die Anzahl der verschiedenen Instanzen hier selbst definieren können. Wir nehmen nur eine große Obermütze. Und wir werden sagen, anstatt, weißt du, spezifisch eine Nummer zu sagen, werden wir nur 20 Frames sagen. Aber das ist natürlich auch nicht ideal. Aber, weißt du, lasst uns das vorerst so sein. Wir werden das Symbol q erledigen und hier, wo die Threads verbunden werden, so weiter. Ok. Also jetzt müssen wir uns unseren Bedrohungen anschließen und einige andere Syntax gezeigt, versuchen und Arbeiter. Lasst uns sicherstellen, dass ihr Lurkers beitritt, okay? Alles klar, also lassen Sie uns das laufen und sehen, ob es funktioniert. Wahrscheinlich Fehler, die wir beheben müssen. Alles klar, also hat unser Postgres-Arbeiter ein unerwartetes Schlüsselwortargument Ausgabe Q bekommen. Also schauen wir uns das an. Postgres-Arbeiter hier. Ich habe eine unerwartete Wahrheit. Wo ist unser Problem? Initialisierte Arbeitskräfte, Arbeitsklasse. Okay, denke also, das Problem ist, dass du Postgres-Masterplaner machst. Nein, das ist nicht das Problem. Postgres-Meister. Und es hat ein unerwartetes Schlüsselwortargument Ausgabe Q bekommen. also unser Protokoll hier betrachten, sieht es so aus, als ob dies sich beschwert, sobald wir die Super-Initialisierung machen. Also vielleicht oder Threading Cloud ist, Threading-Klasse beschwert sich tatsächlich über diese. Also lasst uns das testen. Wir gehen in Python. Wir werden importieren. Schreiben, wir werden Threading Punkt Thread sagen. Und lassen Sie uns einfach versuchen, Ausgabe Q gleich a. Also, das ist, wo das Problem ist. Also werden wir vertrauen, setzen Sie diese Ausgabe Q hier ein, damit wir sie nicht an die Schlüsselwortargumente hier weitergeben. Alternativ können Sie auch tun, ist, dass wir es aus diesem Wörterbuch entfernen können , indem Sie diesen Pop-Aufruf verwenden , der es einfach entfernen wird und uns tatsächlich irgendwie den Wert hier geben, aber es wird nur es aus den Schlüsselwortargumenten entfernen. Also, und hier wollen wir wahrscheinlich etwas Sicherheit haben. Möchten Sie sagen, wenn Ausgabe Q und Schlüsselwortargumente, dann wollten wir es einfach entfernen. Also lasst uns versuchen, dieser Frau Zeit zu laufen. Ordnung. Bisher keine Krankenschwestern, wahrscheinlich gutes Zeichen. In Ordnung. Also haben wir eine Art Timeout erreicht, die okay ist. Aber es sieht so aus, als wäre es fertig. Also hatten wir eine Art Zeit, aus welchem Grund auch immer. Aber dieses Mal komme ich natürlich von hier. So jung. Abgesehen davon sieht es so aus, als würde es funktionieren. Also, das ist eigentlich ziemlich großartig. Das bedeutet, dass wir diesen Code nehmen können und wir sehen was übrig ist und was noch implementiert werden muss. In Ordnung, also natürlich, eines der Dinge, die wir uns bewegen wollen, ist, dass all das nicht sehr nett ist, oder? Wie idealerweise werden wir den Wiki-Arbeiter haben. Und all dieser Prozess, den wir die Werte der Arbeiter halten, wird eingespeist. Und all das wird in diesem Prozess Pipeline-Stumpf getan. Und auf diese Weise müssen wir sie auch hier unten nicht Join und Recurse nennen. Also, wie sollen wir das machen? Also der beste Weg, das oder nicht, ich denke, die Art und Weise, die ich am meisten möchte, ist, dass wir uns irgendwie auf diesen Wiki-Arbeiter erstrecken. Und im Grunde, was wir haben werden, als wollen eine ähnliche Art von Option haben , wo wir diese Meisterklasse haben , für die wir Werte zur Verfügung stellen können. Und von diesen Werten, dann werden wir, wissen Sie, Wiki-Workerinstanzen oder nur eine einzelne Wiki-Workerinstanz haben , vielleicht wird sich das darum kümmern. Was wir also tun können, ist, dass wir einen Wiki-Worker Master-Scheduler haben können. Und wir werden auch tatsächlich eine Threading-Punkt-Thread-Instanz sein . Es ist schon in Kredit für uns. Schön. Der Grund dafür ist, dass wir in unserem YAML-Reader tatsächlich die Join-Methode aufrufen werden. Und andernfalls erhalten wir auf diese Weise wie ein netter Aufruf der Join-Methode, weil sie von der Thread-Klasse geerbt wird. Aber sonst müssten wir es selbst definieren, so dass, wenn wir es „Join“ nennen, es nicht bricht. Und du könntest das sogar tun, indem du so etwas machst. Macht es nur verfügbar. Wissen Sie, wenn, wenn es nicht von der übergeordneten Klasse geerbt wurde, nur damit es in diesem Schritt nicht bricht, so dass wir gleichen Art von logischer Reihenfolge folgen können. Aber lassen Sie uns tatsächlich eine bedroht machen und lassen Sie uns voran und initialisieren Eltern. Hier werden wir Schlüsselwortargumente nehmen. Wiederum häufige Weitergabe an das Threading-Elternteil. Ja, ja. Ende. Was wollen wir in unserem Vicki Arbeiter hier genannt eines der Dinge, die wir tun wollen. Natürlich, kann nicht vergessen, wenn Sie es starten wollen. Und dann müssen wir auch hier die Gebühr entschlüsseln lassen. Und wir werden etwas tun, weißt du, während was auch immer das ist wahr. Ok? Also, was wollen wir in unserem Mickey Master Scheduler? Wenn wir also einen Blick auf unsere Hauptfunktion hier werfen, möchten wir, dass unser Arbeiter im Grunde in der Lage ist, vielleicht verschiedene Eingabe-URLs zu nehmen, einen Wiki-Worker mit jeder URL zu erstellen und dann diesen Wiki-Worker irgendwie seinen Prozess durchlaufen zu lassen indem wir die Symbole erhalten und sie einfach in eine Ausgabe Q setzen. Also, was wir dafür brauchen, als wir brauchen, wenn die Ausgabe Q. Und von hier aus wollen wir sicherstellen, dass Sie die Eingabe-Warteschlange nicht übergeben, weil das die gleiche Beschwerde erhalten wird. Also werden wir sagen, wenn unsere Eingabe q in unseren Schlüsselwortargumenten ist, wir entfernen es einfach und hüpften einfach aus, dass. Und eine andere Sache, die wir wollen, ist, dass wir tatsächlich eine Art von Einträgen wollen, die wir übergeben können, oder? Wie wir keine Eingabe-Warteschlange haben, weil wir nicht aus einer Eingabe-Warteschlange lesen wollten, aber wir wollen Einträge, über die wir iterieren können. Wir werden also sagen, wir gehen davon aus, dass wir weitergehen und Einträge Einträge sagen werden. Und natürlich wollen wir auch keine Einträge übergeben. Also Einträge Raum von hier zu nehmen. Und wir werden wieder so rauskommen. Alles klar, also ja, das ist das Format, das wir wollen. Natürlich wollen wir auch tatsächlich die Ausgabe Q auf den Angeklagten setzen. Und lassen Sie uns tatsächlich die gleiche Syntax verwenden, die wir hier verwenden. Damit wir mehrere Ausgabe QS einstellen können, falls zutreffend. dachten, wie wir es können, wenn wir zurück zu hier gehen, diese Weise, wann immer wir Werte bekommen, wenn wir wollen, können wir sie in verschiedene Ausgabe-Warteschlangen stellen, so dass, weißt du, verschiedene Upstream-Arbeiter sie für alle Zwecke verwenden können. Verwenden Sie das für, in Ordnung, Wenn Q2 und okay, also jetzt müssen wir diese Einträge definieren und wir werden auch unsere Run-Methode hier ändern. Anstatt zu sagen, während wahr, werden wir sagen, für Eintrag und Venture ist, weil jetzt haben wir tatsächlich eine begrenzte Anzahl von Einträgen, die hoffen, dass wir über diese gehen wollen. Und ich bin Rank Sum. Lassen Sie uns unsere YAML-Datei aktualisieren, so dass wir wollen, dass unser Wiki stattfinden wird. Und anstatt Arm freaky Bucher zu initialisieren, wollen wir den Wiki Worker Master Scheduler initialisieren. Wir haben diese Eingabewerte genannt. Also, wenn Sie wollen, können wir von Einträgen hier zwei Eingabewerte aktualisieren. Das ist völlig in Ordnung. Ich muss dafür sorgen, dass wir das natürlich auch hier tun. Ok? Also wollen wir hier Eingangswerte nehmen. Und dann wollen wir für jeden Eingabewert wie diesen über diese iterieren. Und für jeden dieser Eingabewerte wollen wir nur diese Werte in die Symbolausgabe Q hier einfügen. In Ordnung, also haben wir unsere Einträge hier. Also für jeden Eintrag gehen wir dann auf unserem Wiki Corker zu haben, wir wollen dies initialisieren. Wir wollen es tatsächlich mit einer bestimmten URL initialisieren. Was wir also tun werden, ist, dass wir die URL in die Initialisierungsparameter hier verschieben werden. Und auf diese Weise können wir es direkt für die verschiedenen Einträge initialisieren , die wir hier zur Verfügung stellen werden. Und jetzt müssen wir auch, naja, wenn wir zu unserer Hauptfunktion zurückkehren, können wir über die verschiedenen Symbole iterieren und dann wollen wir diese in unsere Ausgabe Q setzen. -Symbolzähler dazu. Der einzige Grund, warum wir dies verwenden, ist, denken Sie daran, dass wir nicht alle Symbole in die Ausgabe Q einfügen , so dass wir alle diese verschiedenen Werte verschrotten, wenden Sie sie in Postgres an. Und vielmehr machen wir nur die ersten fünf, um sicherzustellen, dass es funktioniert. Wir müssen jetzt nicht wie alle 500 machen. Also werden wir diese Unterkunft übernehmen und wir werden haben, ich bin älter. Ich sage vier aus, setze q in unsere Ausgabeschlangen. Also für jede Ausgabe Q, Oops, Nein, wir wollen sicherstellen, dass wir das Symbol dort einfügen. Richtig? Also lasst uns diese Logik hier durchgehen. Also haben wir unseren Wiki-Worker Master Scheduler , der eine Instanz der Thread-Klasse sein wird. Dazu werden wir Schlüsselwortargumente nehmen und Q ausgeben. Und wenn wir nicht q eingegeben haben und wir sicherstellen wollen, dass entfernt wird, so dass wir es nicht an die Initialisierung der Threading-Elternklasse weitergeben . Wir wollen auch Eingabewerte, und diese Eingabewerte werden verschiedene URLs sein, die wir hier so definieren können. Und natürlich, für unsere Ausgabe cuz wollen wir sicherstellen, dass wir die Möglichkeit haben, verschiedene Alpha Cues zu haben, so dass wir hier haben können, zum Beispiel, wie Symbol Q2 und wie zweites Symbol Q. Und wenn wir das haben, lassen Sie mich natürlich auch müssen es hier oben definieren, aber, wissen Sie, nur wenn wir dies auf mehr als ein Q setzen wollen, also bin ich mehr als eine andere Art von Arbeiter kann diese nachgelagerte konsumieren, dass wir diese Option haben. Alles klar, wir wollen sicherstellen, dass wir einen übergeordneten Thread initialisieren. Und dann wollen wir den Prozess starten, genau wie wir es hier tun. Nun, damit dies funktioniert, brauchen wir auch die Run-Methode, die „Art“ genannt wird, von der für uns automatisch gesorgt werden kann , weil wir Eltern werfen. Aber anders als unsere nachgelagerten Arbeiter, die auf Werte warten werden , bis sie aus dem QRS kommen und sie lesen. Anders als das. Wir lesen hier nicht von einem akuten, aber wir lesen aus einem vordefinierten Satz von Einträgen. Also ja, wir wollen nur sicherstellen dass wir den vordefinierten Satz von Einträgen durchlaufen haben, die wir hier drin haben, weil wir bereits wissen, was diese Werte sind. Also müssen wir nicht versuchen, sie von irgendeiner Art Süßer zu bekommen. Also werden wir die verschiedenen Eingabe-URLs durchgehen. Für jede Eingabe erstellen Sie einen Wiki-Worker. Dieser Wiki-Arbeiter kümmert sich um das Verschrotten, also findet man jedes der Symbole. Also werden wir die gleiche Logik hier haben. Und für jedes Symbol, das wir bekommen, wollen wir es auf den Ausgang QS setzen, da wir mehrere olympische Jugend haben können, wollen wir sicherstellen, dass wir über jedes obere Q schleifen und dann dieses Zeug hier, Dies ist wirklich nur so, dass wir nicht 500 Symbole verschrotten, sondern nur die ersten fünf machen, nur um es ein wenig schneller zu machen. In Ordnung, also nehmen wir diese Ausgabe und am Ende. Das ist also auch Logik, dass wir tatsächlich in unseren Quickie-Arbeiter einziehen wollen. Und am Ende hier möchte ich für Ausgabe Q und die oberen Cues sagen. Und dann wieder hier, sagen wir gerade wie eine lächerliche Nummer. 20. Wir wollten sicherstellen, dass wir schicken. Und wir wollen nur, dass das passiert, nachdem alle Symbole gesendet wurden. Und dann, wenn alles vorbei ist, können wir tatsächlich fertig schicken. Also brauchen wir das hier nicht mehr. Wir brauchen sie nicht mehr zu Arbeitern, weil wir das jetzt tun können. Und hier. Und ich schreibe, und schauen wir uns das an. In Ordnung, also lasst uns voran gehen und versuchen, es bekannt zu machen, sehen, was passiert. Sehen Sie, ob wir etwas verpasst haben. Richtig? Es sucht also nach Eingabewerten 0, 0, Kurs und unserem gelben Leser. Wir müssen auch sicherstellen, dass wir passieren hören. Eingabewerte sind also gleich Worker dot. Noch Eingabewerte. Ich werde das hier unten machen. Und ich werde sagen, wenn ich keine Anomalie verwende, dann möchte ich sie in die Initialisierungsparameter setzen. Der Grund, warum ich das tue, anstatt immer den Mittelwert und die Initialisierungsparameter bereitzustellen, wie wir es hier oben tun, ist, weil unsere Eingabewerte wie ein Sonderfall sind, speziell für unsere Wiki-Arbeit hier, Richtig? Denn in all den anderen Arbeitern wird es beschuldigt geben, vielleicht nicht die Angeklagten mit ihnen werden wirklich wie Eingabe- und Ausgabeschlangen sein. Aber unsere Eingabewerte werden wirklich nur für unseren einen Arbeiter hier spezifisch sein. Anstatt es hier einzugeben und dann in den anderen Worker zu gehen und sicherzustellen, dass diese Eingabewarteschlange, werden diese Eingabewerte nicht als Schlüsselwortargumente an den Thread übergeben, wie die Threading-Initialisierung hier. Ich werde es nur weitergeben, wenn es tatsächlich da drin ist, und so muss ich mich nur darum kümmern. Okay, also versuchen wir es nochmal. Bisher kein Fehler, was in der Regel ein gutes Zeichen ist. Aber lassen Sie uns abwarten und sehen, was passiert. In Ordnung. Cool. Es sieht so aus, als ob die Dinge funktionieren. Und ja, wir haben unseren Wiki-Arbeiter jetzt, wo, weißt du, all diese Werte annimmt. Aber natürlich, um sicherzustellen, dass die Dinge funktionieren, Lassen Sie uns einfach voran und drucken Sie in unserem Postgres-Arbeiter erhielt dies nur um zu sehen, ob es den ganzen Weg hinunter kommt . Alles klar, also erhält es Werte. Also funktioniert alles, was genial ist. Es gibt natürlich immer noch eine Sache, die nicht funktioniert, das ist, dass es nicht die ganze Zeit richtig gemacht wird und es ist nicht wie wahrscheinlich ausbrechen. Und der Grund dafür, wenn wir in Yahoo Finance Arbeiter gehen, ist eigentlich, dass es nur hier fertig ist. Und das Problem hier in diesem Fall ist, wenn wir hierher gehen, haben wir zwei Instanzen, aber hier haben wir sechs Instanzen. Sie werden also bemerken, dass der Unterschied, sechs minus zwei vier ist. Wir haben vier Instanzen, die nicht empfangen werden, die Signal jetzt getan werden. Also, was wir jetzt tun können, wird das einfach ausschalten, weil sie ausbrechen. Und wir werden hier sagen, für Alpha Q und oben beschuldigen Ticket wird nur für ich in Reichweite 20 sagen. Für jede Ausgabe Q, wir werden nur eine Reihe von ihnen senden. Natürlich ist das nicht ideal, denn wenn wir 21 Arbeiter und eine Menge von demselben Problem haben, aber im Moment, wissen Sie, sollte es gut sein. So können wir das einfach schnell erneut ausführen. Die andere Sache, die Sie auch bemerken werden, ist, dass es hier keine Instanzen definiert hat. Und so können Sie das sehen, großartig, und alles hat gut funktioniert, weil wir nicht wie die Instanzen hier definiert haben. Das hat sich darum gekümmert. Nun, das ist eine andere kleine Art von Nuance, die wir haben weil wir hier nicht wirklich mehrere Instanzen wollen. Denn wenn wir mehrere Instanzen haben, werden sie nicht aus derselben Warteschlange konsumieren, sondern stattdessen werden sie diesen Prozess wiederholen. Also hier wollen wir eigentlich nicht mehrere Instanzen, denn wenn wir es tun, wie ich schon sagte, werden sie nicht aus einer Warteschlange konsumieren. Sie nehmen also keinen Cue auf und teilen die Arbeit auf. Sie werden die Arbeit wiederholen, weil die Art und Weise, wie dies funktioniert, ist, dass es tatsächlich über diese eingestellten Eingabewerte iterieren wird. Also hier müssen wir vorsichtig sein, dass wir nur 11 Instanz haben. So können wir zum Beispiel auf Notiz verlassen , haben nur eine Instanz hier. Andernfalls verschrotten wir dieses Symbol. Also natürlich, Sie wissen, dass es verschiedene Möglichkeiten gibt, dies zu tun. Eine Sache, die wir tun könnten, ist, dass wir das wieder trennen könnten und Sie wissen, dass unser Wiki-Arbeiter selbst aus einer Warteschlange konsumiert hat. Und wir füttern diese Eingabewerte in q selbst. Aber irgendwann, wissen Sie, müssen Sie zu dem Punkt kommen, wo entweder wir einen Worker haben, der nur eine Instanz hat, die nur alle diese Eingabewerte in eine Warteschlange einspeist , aus der der Wiki-Worker dann verbrauchen könnte. Zum Beispiel könnten wir hier wie ein anderer Arbeiter haben, der nur URL-Zeder sein wird. Und dieser hier kann wie dieser hier nehmen könnte diese Eingabewerte nehmen. Und dann die Ausgabe-Warteschlangen. Warteschlangen können beispielsweise URL-Ausgaben sein. Und dann hier rein und Q setzen, können wir von hier lesen. Und in diesem Fall wird dieser Arbeiter derjenige sein, der nur eine Instanz haben kann. Und vielleicht ist es, weißt du. So wie dieses Problem wird irgendwie wie erweitert nach vorne, nach oben sein. Aber in diesem Fall können wir hier mehrere Threads haben, weil sie nicht mehr von Eingabewerten lesen, sondern sie werden aus der Eingabe-Warteschlange erstellen. Wenn du willst, kannst du damit herumspielen und das umsetzen, damit wir tatsächlich verschiedene UK verschrotten können oder gleichzeitig , wenn wir mehr als eine Instanz hier haben. Aber ja, natürlich, irgendwann werden wir auf dieses Problem stoßen, wo wir nur eine Art Samen liefern müssen . Und wenn wir mehr als eine Instanz haben, die ihnen die C-Richtung und beginnende Duplikate zur Verfügung stellt. Also ja, weißt du, sei dir dessen bewusst, dieses Problem existiert einfach. Und so können wir zum Beispiel eine Notiz hinterlassen, um zu sagen, wie nur eine Instanz hier haben. Und wir können dies sogar noch einmal klarstellen, wir können Instanz eins sagen und wir können sagen: Bitte ändern Sie uns nicht. Ansonsten machen wir doppelte Arbeit, so etwas. Sehen Sie oben notieren. Und wir führen dies noch ein Mal aus, nur um sicherzustellen, dass es gut funktioniert und q dieses nicht existiert. Und wenn alles richtig funktioniert, aber, wissen Sie, nur irgendwie bewusst sein, dass. Wir wollen hier nicht mehr als eine Instanz haben, weil wir diese wie manuell definierte Eingabewerte hier iterieren. Aber es ist für eine Minute. Ja, wenn wir uns unser Ergebnis ansehen und unsere Hauptfunktion ansehen, sehen die Dinge ziemlich toll aus. Das einzige andere, was wir tun können, ist natürlich, wenn wir die richtige Ausführungszeit bekommen wollen. Und wir haben das hier an die Spitze gesetzt, weil sonst wahrscheinlich diese Kupferzeit danach beginnen, aber wir rufen Join-Arbeiter hier an. Also werden wir das erst beginnen, wenn die ganze Arbeit erledigt ist. Also, wenn Sie die richtige Zeit bekommen wollen, und natürlich müssen wir dies oben so setzen. Und wir können auch alle diese ungenutzten Importe hier entfernen , weil alle diese Importe jetzt zu unserem gelben Leser verlegt wurden. Wir können einfach sparen und Gerüchte oder mehr Zeit, um sicherzustellen, dass dies richtig funktioniert. Aber jetzt ist das wirklich schön, weil schauen Sie, wie klein unsere Hauptfunktion geworden ist. Es ist so einfach geworden. Wir haben nur die Pipeline, die wir betreiben wollen. Und dann lassen wir einfach unsere Pipeline ausführen oder die sich um alles kümmert. Und jetzt, wenn wir mehr Arbeit machen wollen, dann können wir das erweitern. Wir können entweder, wenn wir mehr URLs haben, die der gleichen Struktur folgen , die wir glauben, dass unser Wiki-Worker kümmern kann. Dann wissen Sie, wir können hier mehr Eingabewerte eingeben. Wir können dies auf unterschiedliche Perspektiven ausdehnen. Normalerweise haben wir zuvor darüber gesprochen, vielleicht zwei verschiedene Datenbanken oder so etwas zu speichern. Und natürlich, wissen Sie, wenn wir einen zusätzlichen Arbeiter schaffen, müssen wir sicherstellen, dass wir diesen Arbeiter auch definieren. Aber wirklich die ganze harte Arbeit wurde auf den gelben Leser übertragen. Diese Sache kümmert sich tatsächlich dynamisch nur um diese YAML-Konfigurationsdatei hier. Also wirklich, wie wir das so weit erweitern können, wie wir wollen. Natürlich, wie das einzige, was wir tun müssen, wenn wir eine andere Art von Arbeiter hinzufügen, müssen wir sicherstellen, dass wir die Arbeiterklasse und alles wie das definieren und sicherstellen, dass das richtig funktioniert. Aber sobald wir diese Arbeiterklasse zur Verfügung haben, können wir sie wiederverwenden. Wir können unsere Pipelines erweitern, oder? Verschiedene Pipelines. Es gibt eine Menge coole Sachen, die wir tun können und alles, was wir über diese ziemlich lesbare und leicht zu wartende YAML-Datei definieren können. Es ist also so einfach für uns, die Anzahl der verschiedenen Arbeiter, die wir haben wollen, nach oben und unten zu skalieren . Wenn wir zum Beispiel unsere Postgres-Arbeiter einen Engpass sehen. Denn wirklich alles ist nur irgendwie darauf warten, in Postgres gespeichert zu werden , kann die Anzahl der Instanzen erhöhen. Oder wenn es gut geht, können wir es tatsächlich so lassen, wie es ist, oder sogar verringern die Anzahl der Thread ist nicht viele. Wir wollen die Anzahl der Schaber, die wir haben, erhöhen. Also gibt es so viel Freiheit für uns, unsere Pipelines hier abzustimmen. Und all das wurde in diese YAML-Datei und unseren silbernen Code verschoben, wir werden uns einfach dynamisch um all das kümmern. 13. Alle: In diesem Schritt werden wir unsere Kunst YAML Pipeline ausführt aufräumen oder ein bisschen mehr, nur schauen unsere Hauptfunktion hier, wirklich was wir tun, ist, dass wir diesen Prozess Pipeline Schritt nennen, wo wir alles aus wie Laden der Pipeline und dann Initialisierung wie Warteschlangen und Worker. Und dann nennen wir diesen Joint natürlich hier, damit wir warten, bis all diese Arbeiter fertig sind. Und wenn wir nur auf die Art und Weise schauen, dass, Mal sehen wir in unserem Wiki-Arbeiter zum Beispiel hier. Die Art und Weise, wie wir das Senden jetzt erledigen, ist nicht ideal. Denn wirklich, was wir tun, ist, dass wir das, sagen wir, 20 Mal schicken. Was ist, nun, es ist ein bisschen seltsam weil wir uns vorstellen, dass mehrere dieser Arbeiter gleichzeitig laufen. Also in diesem Fall, wenn wir gehen, um zu senden getan, aber einer der anderen Arbeiter ist eigentlich nicht getan. Und wir schicken mehr, als wir so viele Arbeiter im Strom haben, dann werden sie eigentlich alle lesen, und sie werden aufhören. Obwohl vielleicht ein anderer Arbeiter, weißt du, immer noch Werte in diese Warteschlange legt. Nun, natürlich, in diesem Fall, können wir das für den Yahoo Finance-Arbeiter haben, zum Beispiel, die Wiki-Arbeit sind derzeit nicht so sehr weil wir die Instanzen hier auf eins beschränken. Da müssen wir sicherstellen, dass wir im Grunde diese nicht-Duplikate Seed zur Verfügung stellen. Aber das kann nicht mit dem Yahoo Finance Mitarbeiter passieren. Wenn einer von ihnen direkt vor dem anderen endet, und es bringt einfach alles hinein und dann läuft der andere tatsächlich noch und setzt etwas für den Einsatz ein, während dann alle nachgelagerten Arbeiter das lesen und werden tatsächlich nicht die endgültigen Werte erhalten, die nicht in diesem Würfel sind. Lassen Sie uns dies in diesem Schritt ein wenig optimieren. Und lassen Sie uns das Signal von unseren Arbeitern senden und wir werden es in unseren Hauptarbeiter bringen. Im Wesentlichen sind wir gerade kein Arbeiter, ist einfach wie eine Klasse, die uns hilft, die Pipeline auszuführen. Aber eigentlich werden wir Threading importieren. Und wir werden das zu einem Thread 2 machen. Also werden wir es im Grunde zu unserem Hauptarbeiter machen. Und hier, was wir jetzt tun werden, ist, dass wir, naja, natürlich müssen wir den Laufschritt hinzufügen. Hier. Wir werden uns um die Überwachung des Fortschritts und das Senden von erledigten Befehlen kümmern , sobald alles erledigt ist. Also werden wir auch wegnehmen, die Arbeiter beitreten. Denn der erste Schritt, den wir tun werden, sobald dieser Prozess beginnt, ist, dass wir tatsächlich sein werden, während der Prozess-Pipeline-Schritt ausgeführt wird. Und wenn wir uns also hier den Arbeitern angeschlossen haben, dann wird im Grunde alles blockiert, bis wir diesen Punkt erreicht haben. Also natürlich können wir Join-Arbeiter nicht nennen und eigentlich brauchen wir es nicht einmal denn auch hier werden wir wie eine Endlosschleife haben , die sich im Grunde nur um alles kümmert, all das Monitoring kümmern kann, etc, Wand, alles andere ist aktiv. Und dafür müssen wir natürlich auch einfach unseren Thread starten, damit, weißt du, läuft. Okay, also was machen wir hier? Nun, wirklich, was wir tun wollen, ist, dass wir für jeden Arbeiter wissen wollen, vor allem, wie viele, wie das, was q zwei sendet, und auch, wie viele Arbeiter noch am Leben sind. Und dann wollen wir in der Lage sein, zu tun, wenn alle Arbeiter nicht mehr am Leben sind, wollen wir getan an alle Ausgabe-Warteschlangen senden, an die es sendet. Also zum Beispiel, wenn wir drei Ausgabe QS hier haben und diese getan ist, dann wollen wir an alle diese Ausgabe-Warteschlangen getan senden. Und idealerweise hängt die Anzahl der Versendungen auch davon ab, wie viele Instanzen tatsächlich aus dieser Warteschlange verbrauchen. Also werden wir eine separate Sache haben, die uns nur hilft zu verfolgen, wie viele Instanzen sind, wie viele Arbeiter aus jeder Warteschlange konsumieren. Also lasst uns weitermachen und das aufstellen. Und wir werden diesen Teil unserer Initialisierung von Arbeitern machen. Aber zuerst werden wir dies tatsächlich in unsere initialisierte Funktion initialisierte Methode hier setzen . Ich werde ein paar Sachen ausschreiben und erklären, was mit ihnen los war. Wir können wieder zusammenfassen, sobald es aus ist, denn sobald wir es ausgeschrieben haben, wird es offensichtlich ein bisschen einfacher sein, die Logik zu verstehen, anstatt sie in einem abstrakteren Sinne zu erklären. Also werden wir hier Cube Verbraucher haben. Und wir werden auch die Downstream-Hinweise notieren. Die Q Konsumentenvariable wird also im Grunde sagen, für dieses Symbol Q ist dies, wie viele Arbeiter aus dieser Warteschlange konsumieren. Und das Downstream Cuz wird im Grunde immer der Arbeiter sein und was für ein Sinn ist. Dies sind also die zwei zusätzlichen Attribute, die wir hier hinzufügen , damit wir diese Informationen verfolgen können, weil wir sie später brauchen werden. Also, wenn wir jetzt unsere Arbeiter initialisieren, müssen wir den Überblick behalten, nun, vor allem, welche Hinweise es richtig machen? Zwei. So haben wir die Ausgabe QS. Sicher. Hier. Also werden wir haben, wir werden hier in unseren Downstream Cues hinzufügen. Für diesen Worker wird zwei yeas Ausgabeschlangen schreiben. Beachten Sie nun, dass wir die Namen der Ausgabe QS hier nehmen , so dass wir sie später hier referenzieren können. Aber wir müssen nicht wirklich die Instanz der Warteschlange nehmen. Wir können den Namen hier verfolgen. Und dann wollen wir auch wissen, was Q konsumiert wird. Also, wenn wir hier eine Eingabe-Warteschlange haben, und dann können wir sagen, wenn Eingabe q nicht keine ist, dann wollen wir hier dieses Q als von so vielen Arbeitern verbraucht, oder? Je nach Anzahl der Instanzen, die wir hier haben, und das ist, wie viele Arbeiter aus der Warteschlange verbraucht werden. Nun, damit haben wir irgendwie eine implizite Annahme , dass jede Warteschlange für einen Arbeiter sein wird. Wenn wir zum Beispiel einen zweiten Arbeiter haben, der die Ergebnisse von hier nutzen möchte, wird es nicht aus dieser Warteschlange lesen, weil das unsere Werte im Grunde auf zwei separate Arbeiter verteilt , die zwei getrennte Dinge zu tun. Wenn Sie diese Rohdaten irgendwo speichern möchten, dann müssen wir eine separate Ausgabe Q haben, damit wir keine Werte verpassen, die im Grunde die beiden Arbeiter, einer von ihnen wird die Verarbeitung und der andere , das nur die Rohwerte speichert. Sie wollen nicht aus dem gleichen Würfel lesen, weil sie dann irgendwie wie die Daten teilen und einer der Teile davon wird gespeichert und andere Teile der Verarbeitung verarbeitet werden. Aber wir wollen wirklich, jeder Schritt in dieser Pipeline die gesamte Menge von Daten verarbeitet. Also, wenn wir diesen Datensatz 2 benötigen, dann müssen wir eine weitere Ausgabe Q hier hinzufügen, um sicherzustellen, dass wir den vollständigen Datensatz verwenden können. Und mit diesem und dem, was wir hier schreiben, gehen wir wieder davon aus, dass jeder cu spezifisch für einen Arbeiter ist. Also, wenn wir hier vom Symbol Q konsumieren, dann können wir nicht von dem Symbol Q mit einem separaten Worker an anderer Stelle verbrauchen, weil sie sonst die Daten hier aufteilen werden , weil sie alle es einfach nehmen aus. Das ist also eine implizite Annahme, die wir hier machen. Ok? Aber jetzt haben wir, wissen Sie, jetzt wissen wir, an welchen Arbeiter Q jeder Arbeiter schreibt, und auch was q, wie viele Arbeiter aus jeder Warteschlange konsumieren. In Ordnung, also haben wir hier den Run-Prozess. Also, was wir jetzt tun wollen, ist im Grunde, und wir können das in einem Intervall einstellen. Also werde ich auch Zeit importieren, weil dies uns am Ende eine Schlaffunktion ermöglicht. Vielleicht schlafen wir am Ende fünf Sekunden. Damit wir das nicht gerne kontinuierlich machen, aber im Grunde tun dies in Abständen. Also hier werden wir unser Monitoring durchführen. Was wir also tun wollen, ist im Grunde für jeden Arbeiter und für jeden Thread und jeden Arbeiter, wir wollen nur überprüfen, ob er noch läuft. Ähm, was bedeutet das? Wenn wir zum Beispiel unseren Yahoo Finance Worker betrachten, wenn wir hier aus dieser Schleife brechen und im Grunde diese Methode zu Ende geht, dann läuft der Arbeiter nicht mehr. An diesem Punkt ist der Arbeiter nicht mehr am Leben. Und so wollen wir im Grunde nach den Punkten suchen, wenn dieser Worker zum Beispiel aus seiner Run-Schleife ausbricht oder seine Run-Methode hier beendet. An diesem Punkt ist es nicht mehr am Leben. An diesem Punkt wissen wir, okay, dieser Arbeiter ist fertig. So können wir anfangen zu senden und an die nachgelagerten Verbraucher zu tun. Natürlich, wenn wir mehr Instanzen haben , als wir müssen sicherstellen, dass es nicht nur eine Instanz ist, die fertig ist, sondern dass jede Instanz beendet ist. Also, was wir tun werden, ist, dass wir für Arbeiter sagen, Arbeitername rein, und jetzt wollen wir nur unsere Arbeiter mitnehmen. So schleifen wir uns über unsere Arbeiter. Und hier werden wir den Überblick über die gesamte Lebensdauer der Arbeiter-Threads behalten. Da jeder unserer Mitarbeiter mehrere Threads haben kann, möchten wir nur die Gesamtzahl der aktuell laufenden Threads verfolgen. Also werden wir uns über jede Seite schleifen. Wir werden sagen, für Worker-Thread, genau wie hier, schleifen über jeden Thread, den wir hier verfolgen. Wie können wir überprüfen, ob es Lifo ist? Es ist eigentlich relativ einfach. Alles, was wir tun müssen, ist, dass wir unseren Thread nehmen und wir können einfach verwenden, diese Methode ist am Leben. Und das wird uns sagen, ob der Arbeiter noch am Leben ist oder nicht. Also können wir sagen, ob ein Arbeiter am Leben ist. Dann wollen wir das nur um eins erhöhen. Also im Grunde für jeden Arbeiter, den wir haben, das ist am Leben, dann werden wir das um eins erhöhen. Und so im Vordergrund, wenn wir keinen von diesen Arbeitern am Leben haben, also wenn alle Threads fertig sind, können wir jetzt anfangen, die Downstream-Hinweise von hier aus zu nehmen, und wir können anfangen, es zu senden. Also können wir sagen, alles, was wir brauchen, um die Downstream Cues zu bekommen. Und vier hier, wir müssen zuerst überprüfen, wenn nicht gar keine, weil wir keine Fälle haben können. Zum Beispiel hat unser Postgres-Worker keine Ausgabe-Warteschlangen. Also wollen wir sicherstellen, dass die nachgelagerten Hinweise, die wir haben, dass diese existieren. Also, wenn Reduktion Cues oder nicht keine, dann wollen wir, für Downstream Q in den Downstream Cues, die wir für jeden Worker haben. Also, was wir tun, ist, dass wir über schleifen, Hier ist eine YAML-Datei. Wir schleifen über jede dieser Ausgabe QS hier. Da dies der Fall ist, was wir in dieser Downstream-Cuz-Variable verfolgen, ist, dass wir alle Ausgabe-Warteschlangen verfolgen. So können wir dies für Downstream Q nennen. Wir können diese Ausgabe Q aufrufen, um irgendwie eher konsistent mit einer Syntax zu sein , die wir hier haben. So können wir dies verwenden, um für jede Ausgabe Q und hier zu routen. Dann wollen wir eine Anzahl von Verbrauchern haben. Also jetzt wollen wir für jede Ausgabe Q wissen, wie viele Threads tatsächlich von hier gelesen werden. Nun, wir verfolgen das genau hier. So wissen wir für jedes q, wie viele Threads oder Lesen davon. Also die Zahl der Verbraucher hier. Wir können einfach aus diesem Wörterbuch lesen, das wir hier eingerichtet haben. Und dann können wir für mich in der Reihe Zahl der Verbraucher sagen. Und jetzt für jeden von diesen, können wir diese Ausgabe Q getan senden. Also müssen wir tatsächlich diese FAQ zu bekommen. Also und ich werde, ich werde irgendwie in einer Sekunde zusammenfassen. Aber zuerst schreiben wir das einfach aus, damit wir, wissen Sie, die ganze Sache hier haben . Also werden wir unsere Ausgabe Q nehmen und genau wie wir hier haben, werden wir fertig machen. In Ordnung? Ok? Und dann die letzte Sache, die wir vielleicht tun können, wenn wir nicht mehr von diesen Bedrohungen am Leben haben, dann können wir tatsächlich entfernen, können wir diese Art von Arbeiter aus unserer Verfolgung entfernen , so dass wir keine Spur mehr brauchen. Und jetzt, okay, wie sollen wir dieser Endlosschleife ausgehen, während wir auch den Überblick über die gesamten Arbeiter am Leben behalten wollen . Und im Grunde können wir das hier oben wahrscheinlich tun, weil wir dies bei jeder Iteration im Auge behalten wollen. Jedes Mal, wenn wir durchmachen und für jeden der Arbeiter, wollen wir wissen, wie viele Arbeiter und insgesamt lebendig. Wir werden über alle Arbeiter gehen. Und dann können wir hier tatsächlich sagen, nun, wir können entweder tun, solange wahr, und dann können Sie hier sagen, wenn die Gesamtzahl der Arbeiter gleich 0 ist, dann können wir daraus ausbrechen. Oder wir können sagen,, während insgesamt Bucher leben, weil ungleich 0. Aber dann müssen wir es hier oben definieren und schreien. Also in diesem Fall ist jede dieser Optionen irgendwie in Ordnung. Und es hängt wirklich davon ab, was Sie wollen, denke ich hier. Nun, da wir das jetzt haben, und wir werden einfach mit dem gehen. Es ist etwas peinlich, diese Duplizierung hier zu haben. In diesem Fall könnte ich es auch nach hinten legen, so dass wir im Grunde erzählen, den Zähler ganz am Ende zurücksetzen. Aber wirklich läuft es nicht gut. Wir wollen den Zähler eigentlich nicht ganz am Ende zurücksetzen, weil wir dann aus dieser Schleife ausbrechen würden. Also ja, wir wollen es hier ganz oben haben. Okay, also lasst uns einfach durchgehen, was wir haben. Und das erste, was ich auch tun werde, ist, dass ich all dieses Zeug einfach kommentieren werde, weil wir nicht mehr wollen, dass unsere Threads natürlich diese getätigten all dieses Zeug einfach kommentieren werde, weil wir nicht mehr wollen, dass unsere Threads Signale senden. Aber stattdessen wollen wir, dass unsere Hauptpipeline dafür verantwortlich ist. Also, was haben wir gerade gemacht? Nun, zuerst haben wir die Join-Worker aus unserem Prozess-Pipeline-Schritt genommen. Denn wenn wir das tun, dann wird dieser Schritt hier im Grunde blockieren und das wollen wir nicht. Also haben wir das hier aus diesem Schritt genommen. Und in unseren initialisierten Arbeitskräften haben wir zwei zusätzliche Attribute hinzugefügt, die wir verfolgen. Jeder von ihnen hat ein Wörterbuch. Also für jeden Arbeiter, um zu verfolgen, was Q, sie senden zwei. Also verfolgen wir ihre Ausgabe Q. Und für jede q, wir sind auch, sind für jeden Arbeiter, wir verfolgen auch, was q sie lesen und wie viele Instanzen aus der Warteschlange lesen. Auch hier geht man davon aus, dass jeder Cue spezifisch für einen Worker ist. So können wir zum Beispiel das Symbol Q nicht wiederverwenden. Hier, wie das funktioniert nicht, weil dann werden sie die Daten, die von hier kommen, verbreiten. Und das wird etwas davon lesen, und das wird etwas davon lesen. Aber keiner wird den vollständigen, vollständigen Datensatz erhalten . Also können wir das nicht tun. Also mit dieser Annahme sagen wir im Grunde, Okay, jede Art von Arbeiter und wir können die Anzahl der Instanzen hier skalieren immer noch kein Problem. Aber jede Art von Arbeiter, die wir hier haben, hat eine spezifische Warteschlange damit verbunden, so dass wir jetzt wissen, okay, für jedes q, wir wissen, dass dies ist, wie viele Instanzen davon konsumieren, die wir hier sehen können. Okay, jetzt behalten wir nur den Überblick über diese Q-Statistik. Also, dass später, wenn wir diese Ausführungsmethode aufrufen oder, und dann die nächsten Schritte dieser Ausführungsmethode und bringen Sie den Lauf verwenden, weil wir dies in eine Threading-Klasse umgewandelt haben. Wir starten jetzt eine Schleife, die im Grunde verfolgen wird wie Überwachung für uns in einer Hand. Wir werden das Monitoring in einer Sekunde umsetzen. Aber auch wird es sich um das Senden an die Ausgabe-Warteschlangen kümmern. Was wiederum wichtig ist, denn wenn wir es hier tun, als eine Bedrohung beenden könnte, könnte ich anfangen, fertig zu senden, und ein anderer Thread könnte ausgeführt werden, und es wird tatsächlich Werte hinzufügen, nachdem das getan hier wurde gesendet. Aber, weißt du, damit senden wir 20 Nachrichten. Dann werden die nachgeschalteten Verbraucher eigentlich alle anhalten, weil sie den w1-Wert bekommen werden. Und dann werden sie einige Nachrichten in der Warteschlange sein, die ungelesen bleiben. Also wollen wir das vermeiden und wir wollen nur dann erledigen, wenn jeder einzelne Arbeiter fertig ist. Die Art und Weise, wie wir das tun, ist, dass wir über jeden Arbeiter, den wir haben, schleifen. Und für jeden Worker gehen wir über jeden einzelnen Thread und wir überprüfen nur, ob dieser Thread am Leben ist oder nicht. Und jetzt bedeutet das, dass ein Thread nicht mehr am Leben ist , wenn er seine Ausführungsmethode hier beendet. Wenn es also aus dieser Laufschleife herausbricht, ist dieser Punkt des Threads nicht mehr am Leben. Und das würde nicht auslösen. Aber wenn es noch am Leben ist, bedeutet das, dass es hier immer noch in dieser Laufschleife ist. Und so behalten wir nur den Überblick über die Gesamtzahl der Worker-Threads, die am Leben sind. Und wenn keiner der Threads am Leben ist, bedeutet das, dass jeder einzelne Worker beendet ist. Es ist ausgebrochen, wenn es Schleife ist. Dann wissen wir, okay, jetzt wollen wir an alle Hinweise senden, an die es schreibt. Also müssen wir jede einzelne Ausgabe Q durchlaufen, m für jede einzelne Ausgabe Q, wir müssen eine Reihe von Malen basierend auf dem Worker senden , der aus dieser Warteschlange liest, die diese ist. Wie viele Instanzen diese Bar? Zum Beispiel haben wir in diesem Fall sechs Instanzen, die vom Postgres-Hochladen gelesen werden. Und so wollen wir sicherstellen, dass wir mindestens sechs Mal fertig senden , damit jede einzelne Instanz hier die fertige Nachricht liest. Und das ist die Logik, die wir hier implementiert haben. Und dann, ganz am Ende, nehmen wir diesen Arbeiter einfach aus der Verfolgung, so dass, weißt du, sobald es fertig ist, als müssten wir nicht mehr wirklich dasselbe tun. Wir wissen, wie wenn wir das alles hier erledigt haben, dann wissen Sie, dass dieser Arbeiter vollständig fertig ist. Wir müssen es nicht mehr verfolgen. Es gibt also noch eine Sache, die ich hier hinzufügen möchte, die Arbeiterstatistiken sein wird. Und was ich hier tun will, ist einfach den Arbeiternamen hinzuzufügen, sowie wie viele Arbeiter am Leben sind. Und dann wollte ich ganz am Ende hier Autoworker-Schritte ausdrucken. Jetzt ist das nur eine Art Überwachung für uns, damit wir sehen können, was vor sich geht. Und hier in unserem Hauptthread habe ich diese Prozesspipeline ersetzt, war nur der Startschritt, so dass wir diese Ausführungsmethode hier tatsächlich starten. Okay, also aktivierst du nicht nur meine virtuelle Umgebung. Und dann gehen wir voran und laufen und tatsächlich müssen Postgres einschalten. Da derzeit meine Postgres-Instanz oder Postgres-Server nicht lokal ausgeführt wird, müssen Sie nur sicherstellen, dass das gestartet wird. Also mal sehen, da gehen wir. In Ordnung, also gehen wir weiter und lassen Sie das laufen. Okay, wir haben hier einen Fehler. Die Initialisierungsmethode wird nicht aufgerufen. Deshalb wollen wir natürlich auch die Bedrohung initialisieren. In Ordnung, also lasst uns das noch einmal versuchen. Okay, also läuft es wieder. Also für das derzeit, na ja, vor allem, haben wir diese Extraktionszeit wieder, was nur deshalb ist, weil wir sie nicht Join-Methoden nennen. Also das ist irgendwie dasselbe, was wir hatten, bevor es regnet, weil wir hier nicht angerufen werden. Es springt im Grunde, fast sofort zu hören. Aber die andere Sache ist, es scheint, als würden wir die Statistiken hier noch nicht ausdrucken. Also werde ich natürlich. Das ist ein Irrtum hier. Wenn wir dies hier oben auf 0 setzen, dann werden wir natürlich nicht einmal diese Schleife betreten. Also lassen Sie mich das reparieren. Und einfach hier oben, sag, das war irgendwie mein Knopf. Wenn wir dies auf 0 setzen, wenn hier, und dann, wenn wir sagen, während dies nicht 0 ist, na ja, das ist bereits 0, so dass wir nicht einmal gehen, um diese Schleife zu betreten. Also nimm das raus. Aber es gibt noch eine Sache, die ich tun wollte, nämlich eine Liste von Arbeitern zu haben, die wir löschen sollten. Und anstatt es sofort hier zu löschen, möchte ich diesen Workernamen tatsächlich anhängen und ihn später löschen. Also möchte ich in der Lage sein, vielleicht für Arbeiter zu hören und hier zu löschen, ich wollte es führen. Der Grund dafür ist, dass wir, wenn wir hier oben gelöscht haben, immer noch iterieren, als ob wir das immer noch durchlaufen. Und zum Löschen, während wir schleifen, dann wird Python auf uns verärgert sein. Also wollen wir das nicht tun. Wir wollen nur entfernen, wenn wir die Schleife beendet haben, weshalb ich sie irgendwie so behalte. Also lasst uns das noch einmal versuchen. Okay, da gehen wir. Jetzt sehen wir also unsere tatsächlichen Arbeiterstatistiken. So können wir unseren Wiki-Arbeiter hier fertig sehen. Und wir haben auch bemerkt, wie ich hier oben ging. Wir sehen hier eigentlich neun Arbeiter, was natürlich nicht wahr ist. Dies ist nicht falsch unsere Überwachung, weil wir hier die Gesamtzahl der Worker-Threads lebendig zeigen wollen, nicht die Gesamtzahl der lebenden Replikate, was es irgendwie aggregiert ist. Jetzt etwas, das passieren sollte, aber nicht wirklich passiert. Und ich werde nur diese Schlafzeit hier abnehmen , nur um sicherzustellen, dass das kein Problem ist. Aber wir können durch unsere Protokolle gehen sehen, dass unsere Mitarbeiter tatsächlich Timeouts erreichen und dass sie nicht von unseren Stop-Signalen gestoppt werden. Also natürlich wollen wir das nicht. Wir wollen sicherstellen, dass Ihre Timeouts Atome erreicht werden. Also wollen wir das nicht. Wir wollen sicherstellen, dass unsere Arbeiter tatsächlich mit der Methode aufhören, die wir tun, die wir hier haben. Also nochmals einen Blick auf unsere Schleife zu werfen, na ja, das sollte nicht sein. Weil wir gehen wollen, wenn wir tatsächlich nachgeschaltete Arbeiter haben. Also lasst uns das noch einmal versuchen. Und da gehen wir. Also jetzt beheben wir das Problem, das wir früher hatten, das war, dass wir nicht von hier aus gesendet haben, sondern wir haben Timeouts erreicht. Und natürlich können wir sehen, dass es toll war, diese Timeouts zu haben, weil es irgendwie hilft, einige der tatsächlichen Fehler zu bekämpfen, die wir hier hatten. Wir waren nicht irgendwie in einer Endlosschleife stecken. Aber ja, also haben wir diesen Teil irgendwie fertig gestellt, was eigentlich sehr nett ist, weil wir jetzt nicht mehr von hier aus senden. Also lasst uns weitermachen und das auch entfernen. Und auf diese Weise, wenn wir mehrere Instanzen haben, dann ist es nicht, wenn die erste beendet ist und es fertig sendet, dann, wissen Sie, alles andere Downstream wird aufhören. Und selbst wenn wir nur einmal erledigt schicken, dann gingen wir in Probleme wie das, was passiert, wenn die Anzahl der nachgelagerten Arbeiter nicht gleich der Anzahl der Arbeitskräfte ist , die wir derzeit haben. Wenn wir mehr nachgelagerte Arbeiter haben und sie nicht fertig werden und sie werden Timeouts erreichen. Und selbst wenn sie es tun, dann werden sie aufhören, bevor alle Arbeiter er er F-Stop, was bedeutet, dass unser Durchsatz sinkt. Also, es auf diese Weise zu haben, ist es viel schöner, denn jetzt schicken wir fertig. Sobald wir das alles kennen, sind alle diese Arbeiter tatsächlich fertig. Jetzt gibt es noch eine kurze Sache, die ich Ihnen zeigen wollte und ich weiß, dass wir hier etwas lange werden, aber eigentlich können wir das nicht ausführen, weil es leider nicht auf dem Mac funktioniert, aber das funktioniert unter Linux. Also verfolgen wir hier unsere Arbeiterstatistiken. Und wir würden wahrscheinlich nicht gerne eine ähnliche Sache für q sagen, dass es richtig ist, verstehen Sie einfach, wie viele Daten tatsächlich in unseren Cues sind. Nun gibt es diese Methode, wenn wir uns die Warteschlange ansehen. Also nochmal, wird es nicht so sein , als würde es sowieso nicht laufen. Aber wir können sagen, wie für Q in, in unserem QRS und dann nur mit dieser Warteschlange. Und dann hier können wir uns die Warteschlangengröße ansehen. Also das ist wieder etwas, das nicht alle verfügbar ist, leider auf Mac, aber unter Linux ist das etwas, das Sie tatsächlich tun können, ist, dass Sie die Warteschlangengrößen erhalten können. Nun, ähm, und das ist einfach wirklich nett, weil man im Grunde überwachen kann, wie viel in jeder Warteschlange ist. Und damit, dann können Sie sagen, Oh, okay, Sie kennen so viele Arbeiter oder haben, aber ich kann tatsächlich sehen, wie, oh, dieses Q super voll. Also werde ich tatsächlich mehr Instanzen hinzufügen und vielleicht nehme ich einige Arbeiter woanders heraus, wo die Warteschlangengröße immer 0 ist. Also, dieses Q-Monitoring-Tool zu haben, ist auch wirklich schön. Und natürlich können wir es in wie auch oh, Q beginnt so. Und dann können wir hier, weißt du, genau wie wir es vorher getan haben, anstatt das einfach auszudrucken. Sie können das hier hinzufügen und dann hier können wir wie beschuldigte Punkte ausdrucken. Jetzt leider, und Sie werden sehen, ob ich das ausführe, wird dies einen Fehler verursachen, weil dies im Grunde nicht sanft auf Mac implementiert ist. Dies würde also auf einem Linux-System laufen, aber leider läuft es nicht auf Mac. Also, ja, wir können es hier nicht benutzen. Aber die meiste Zeit, wenn Sie tatsächlich Dinge in der Produktion verwenden möchten und es wahrscheinlich auf einem Linux-System ausgeführt wird, weil es wie ein Docker-Image oder so etwas bereitgestellt wird. In diesen Fällen können Sie diesen Code tatsächlich in der Lage lassen. Außerdem können Sie die Warteschlangenstatistiken überwachen. Und damit, dann werden Sie in der Lage sein, mehr Informationen zu erhalten, indem Sie durch die Protokolle gehen. Skalieren Sie die Anzahl der Postgres-Instanzen. Ich skaliere die Anzahl der Instanzen vielleicht, weil es immer 0 ist. Und so hat es keinen Sinn, so viele Instanzen zu haben, wenn unser q immer 0 ist. Und so ja, ohne hoffentlich sind Sie in der Lage, diese Informationen, die Sie bekommen, zu nehmen und intelligentere Entscheidungen darüber zu treffen, wie Sie sind, wie viele Instanzen Sie tatsächlich jedem der verschiedenen Arbeiter zuschreiben , die Sie hier haben. Aber ja, so etwas bringt uns hier zum Ende dieser Optimierung. Und wir kommen tatsächlich sehr, sehr nah daran, das zu beenden. Also das einzige, was wir im nächsten Video behandeln werden, ist im Grunde, wir wollen einige der Definitionen, die wir haben, nehmen, speziell wie die Pipeline-Position oder so. Und wir wollen, oder ich möchte es wie eine Umgebungsvariable einfügen. Aber noch einmal werden wir in der nächsten Lektion darüber sprechen. 14. Final: Alles klar, in dieser Lektion werden wir nur eine schnelle Säuberung durchführen, im Grunde gehen und dies nur in eine Umgebungsvariable verschieben, aber dann haben wir auch eine lokale Umgebungsvariable, die wir für tatsächliche Tests und Sachen verwenden können wie das. Also nur, dass all dies wie ein bisschen freier wird , basierend darauf, wann immer wir das Programm starten wollen, können wir es irgendwie auf diesem Sinn definieren. Also sind Sie natürlich das erste, was wir tun werden, ist, dass wir sagen, dass diese Umgebung wird, ich werde das nur unseren Pipeline-Standort nennen. Und hier müssen wir auch OS importieren. Nun, was ich tun werde, ist, dass ich eine Punkt-ENV-Datei erstellen werde, die unsere Umgebungsvariablen sein wird. Und ich bin eigentlich, lassen Sie mich das umbenennen, weil ich diesen Gedanken und lokal nennen werde. Das wird also wie unsere lokalen Umgebungsvariablen sein. Das bedeutet, wenn wir später wie Staging- und Produktionsumgebungsvariablen haben wollen, dann können wir jede dieser n ändern, je nachdem, was wir testen möchten. Wir können verschiedene Dinge gebrauchen. Ich bin hauptsächlich Sie wollen wahrscheinlich auf lokalen und Inszenierungen testen. Also werden wir hier unsere Umgebungsvariablen definieren. Und wir werden das einfach hier rüber nehmen. Was uns dieser Experte erlaubt, in einer Sekunde zu tun, wenn wir diesen Quellbefehl verwenden, ist, dass wir in der Lage sind, die Umgebungsdatei zu beziehen. Und dann, was es bedeutet, ist, dass dieser Export einfach diese Umgebungsvariablen in unserem Terminal hier setzen wird . So können wir sie einfach, wissen Sie, in unserem Terminal, in unserer laufenden Terminal-Instanz definieren lassen. Und wenn wir es ausführen, dann werden wir diese Umgebungsvariablen verwenden. Also fügen wir die Pipeline-Position hinzu, aber tatsächlich, lassen Sie uns durch eine andere Arbeiter gehen, weil wir in unserem Postgres-Worker auch Umgebungsvariablen verwenden. Also haben wir Postgres-Benutzer , der nur eine leere Zeichenfolge sein wird. Wir haben das Postgres-Passwort, das auch eine leere Zeichenfolge sein wird, und der Mac-Fall im Windows-Fall hier werden Sie Werte hier eingestellt haben. Der Postgres-Gastgeber wird unser lokaler Gastgeber sein. Und die Postgres-Datenbank wird das sein, was wir hier haben. In diesem Fall werde ich das von hier entfernen. Auf diese Weise haben wir es nur hier definiert. Soweit ich weiß, ist diese Beschaffung von Umgebung und diese Syntax spezifisch für Linux- und Mac-Systeme. Aber wissen Sie, wenn Sie auf einem Windows sind, können Sie immer noch die ähnliche Syntax wieder haben, wie wir über die letzte Lektion gesprochen haben. Sie werden tatsächlich sein, wissen Sie, wenn Sie es tun oder jemand anderes Ihnen hilft, es irgendwo bereitzustellen, dass dies meistens immer im Gegensatz zu einem Linux-basierten System ausgeführt wird. Also, wissen Sie, Sie werden in der Lage sein, diese Umgebung zu nutzen. Und die Umgebungssyntax würde auch auf einem Windows funktionieren. Aber genau wie diese ausnutzende Syntax auf diese Weise bin ich mir ziemlich sicher, dass genau wie Linux und Mac spezifisch ist. Aber mach dir keine Sorgen, denn das ist irgendwie wie die letzten Schritte der Aufräumung. Und wieder, wenn Sie es woanders ausführen, können Sie diese Umgebungsvariablen tatsächlich übergeben. Und so haben wir hier unsere Umgebungsvariablen. Und wir haben hier. Hier müssen wir sagen, wenn wir keinen Pipeline-Standort haben, dann werden wir im Grunde mit einem Exit-Code beenden. Sets fehlgeschlagen und wir werden sagen, ich bin Pipeline-Standort nicht definiert. Und dann, wenn wir die Extraktionszeit Ihrer Tube haben wollen, weil unser Hauptausführer, unsere YAML I Executoren eigentlich auch eine Bedrohung jetzt, nun, wir könnten es gut machen, wir könnten das wie Arbeiter zeigen nennen. Aber wir wissen wirklich, unser Hauptthread hier, oder unser gelber Arbeiter-Thread, nur dann die Anode verlassen wird, wenn alle Arbeiter und Saturn fertig sind. Also, nur wenn alle Arbeiter im Inneren fertig sind, werden wir eigentlich gerne hier rausbrechen? Also wirklich können wir es auch einfach anrufen, rufen Sie den Join hier an, wenn wir diese Extraktionszeit bekommen wollen. Also lasst uns voran gehen und testen, wie das funktioniert. Wir werden unsere lokalen Umgebungsvariablen aktivieren, damit wir sehen können , ob ich diese Variable ausdrucken möchte. Okay, jetzt ist es definiert. Und dieses Echo ist nur ein Terminal-Befehl, den wir verwenden können. Und dieses Dollar-Symbol bedeutet hier im Grunde , dass wir den Wert einer Variablen drucken wollen, die wir hier definiert haben. Das ist also sehr ähnlich, genau wie das Definieren von Variablen in Python nur, die Syntax ist ein wenig anders für das Terminal, aber es druckt im Grunde den Wert der Pipeline-Position aus. Und hier definieren wir die Pipeline-Positionsvariable, um diesen Wert zu haben. In Ordnung, also lassen Sie uns versuchen, unsere Hauptfunktion erneut auszuführen und nur sicherzustellen, dass alles richtig funktioniert. Und nachdem wir diese Änderungen vorgenommen haben , wie es aussieht. In Ordnung, und so haben wir auch die richtige Extraktionszeit. Und dann noch eine Sache, die ich tun möchte, ist , dass wir wahrscheinlich nicht ständig das ganze Zeug ausdrucken wollen. Weißt du, das ist eher für Testzwecke, während wir ihn hatten. Also können wir den Druck einfach entfernen und ich führe ihn noch einmal aus, nur um sicherzustellen, dass die Ausgabe auch sauber ist. Also sieht alles wirklich sauber aus. Und ja, da gehen wir. Diese Art von wie bringt uns könnte auch diese im Grunde alle unnötigen auskommentierten Sachen entfernen . Und ja, diese Art von bringt uns zum Ende dieses ganzen Threading-Tutorials, wo wir aufgebaut haben und wissen Sie, dieses ganze Threading-Programm zu tun wie Verschrottung und Datenbank-Upload und all das Zeug, nur um herum zu kommen. Die Probleme sind wie die Timeouts, die wir zu der Zeit erlebt haben waren die Wartezeiten, die mit der Netzwerkkommunikation verbunden sind. Ich hoffe, dass Ihnen das gefallen hat, Sie haben viel gelernt und Sie können etwas davon entweder auf Ihre eigenen Projekte oder Ihre eigene Arbeit übertragen . Und wieder, nutzen Sie dies speziell in Fällen, in denen die begrenzenden Faktoren Netzwerkkommunikationszeiten sind. Auch hier ist Threading nicht optimal, um Rechenbelastungen zu optimieren , da wir nicht mehr wie CPU verwenden. Es ist gerade dann, wenn wir darauf warten, dass Netzwerke reagieren. Wir haben Netzwerkkommunikation, als andere Threads weiterhin ausgeführt werden können , während die anderen Threads nur auf eine Antwort von irgendwo anderem über das Netzwerk warten. Also wieder, wissen Sie, tolle Arbeit, um diesen Abschnitt des Kurses abzuschließen. Ich hoffe, Sie haben es genossen. Ich hoffe, du hast viel gelernt. 15. Einragen: Alles klar, jetzt, da wir diese ziemlich coole Threading-Anwendung gebaut haben und etwas , das wir viel im Inneren verwendet haben, waren alle diese Hinweise, die, wenn Sie sich am Anfang erinnern, als wir über die QRS gesprochen haben. Mal sehen, wo wir sie hier initialisieren. Also sprachen wir darüber, dass diese Thread-sicher sind. Also, was genau bedeutet das? Und diese Lektion, Ich wollte schnell über Sperren gehen und etwas bekannt als ein Rennen Bedingungen, so dass Sie einige Dinge verstehen, die Sie müssen vorsichtig sein, wenn Threading tun. Also werde ich hier eine neue Datei erstellen. Ich werde nicht abschließen anrufen. Und was wir hier tun werden, ist, dass wir nur Threading importieren. Und wir werden eine kleine Funktion haben. Wir werden einen globalen Zähler haben, der auf 0 gesetzt wird. Und wir werden eine kleine Funktion namens increment haben. Und das wird unseren Zähler nehmen und wir werden nur eine Schleife hier haben. Wir werden sagen, für ich in Reichweite, und dann beginnen mit 10. Ich benutze Kräfte von 10 hier, so dass On-Off, um zehn und dann eine 100 und 1000 zu schreiben. Also werde ich Kräfte von 10 verwenden, nur um das ein bisschen einfacher zu machen , und du wirst in einer Sekunde sehen, warum. Also werden wir hier eine Schleife haben, die derzeit nur zehn Iterationen durchführt. Und während jeder Iteration wird es einen Zähler nach dem anderen implementieren. Nun, hier rufe ich nur die globale Variable auf, falls Sie das noch nicht gesehen da wir diesen Wert ändern, müssen wir tatsächlich sicherstellen, dass wir die globale Variable oben hier aufrufen, da wir nicht nur darauf zugreifen, aber wir modifizieren es tatsächlich. Also, was ich jetzt tun werde, ist, dass ich vier Threads erstellen werde. Ich werde sagen, für mich in Bereich vier, wir werden einen Thread erstellen. Und unser Ziel wird diese Inkrementfunktion sein. Und dann werden wir diese einfach anhängen und dann beginnen wir sie alle. Also werden wir sagen, t dot start. Und dann werden wir auch die Join-Methode aufrufen , um sicherzustellen, dass wir warten, bis sie alle fertig sind. Und ganz am Ende werden wir unseren Gegenwert ausdrucken. So ziemlich unkompliziertes Programm. Wirklich, was wir tun, ist, dass wir hier eine globale Variable haben, Counter initialisiert auf Sigma. Und dann haben wir nur eine Funktion, die diese globale Variable nimmt , die zehnmal erhöht wird. Und wir werden das über vier Threads laufen. Jeder Thread wird also diese Funktion aufrufen. Insgesamt sollten wir hier einen Wert von 40 haben. Da wir vier Threads haben, ruft jeder Thread die Funktion auf. Jeder Funktionsaufruf wird diesen Wert um 10 erhöhen, also 4 mal 10, das wird 40 sein. Also lasst uns weitermachen und das laufen. Alles klar, denn es sieht ziemlich gut aus. Versuchen wir also, diese Zahl hier zu erhöhen. Statt zehn zu tun, Lasst uns es 1000. Also wird es 10 zu den 3 sein. In Ordnung? Und lasst uns weitermachen und das laufen. Okay, viertausend, das ist genau das, was wir erwarten. Versuchen Sie, dies noch einmal zu erhöhen. Anstatt 1000 Operationen zu machen, werden wir jetzt eine Million tun. Also, was wir hier erwarten, wird 4 Millionen sein. Seit jedem Wert werden wir nur eine Million Mal inkrementieren und wir werden das über vier Threads tun. Also lasst uns weitermachen und das laufen. Oh, das ist komisch. Warum kriegen wir das und nicht 4 Millionen? Was uns hier begegnet ist, ist etwas, das als Race-Bedingung bezeichnet wird, wo wir im Grunde eine gemeinsame Variable haben, wo wir im Grunde eine gemeinsame Variable haben, was wir hier haben. Und mehrere verschiedene Entitäten versuchen gleichzeitig darauf zuzugreifen. Was also irgendwann passiert ist, ist, dass wir unseren Zähler haben, gleich welchem Wert x ist und dann haben wir einen Thread. Ein Thread liest es und es sieht oh, Zähler x und dann wird es versuchen, es danach zu erhöhen. Aber zur gleichen Zeit haben wir einen anderen Thread, sagen Thread T2, der sieht auch Zähler gleich x ist. Also, was passiert ist, wenn wir Thread haben, sagt man Zähler gleich Zähler plus eins ist. Das bedeutet also, dass ein Essenzzähler gleich x plus 1. Und dann haben wir auch Faden daran, dasselbe zu tun. Also haben wir in diesem Fall ist das Ergebnis, das wir bekommen, ist tatsächlich Zähler gleich x plus 1, obwohl wir zwei Threads darauf zugreifen hatten. Und der Grund dafür ist, dass diese Werte manchmal im Grunde dasselbe sehen und dann ihre Operationen nennen, aber sie haben es nicht nacheinander gelesen. Sie haben also keinen nach dem anderen gelesen. Es wurde nicht so hingerichtet. In diesem Fall hätten wir hier den richtigen Wert gehabt, aber sie lesen ihn zur gleichen Zeit oder nahe genug, bevor diese Inkrementoperation passieren kann. Das Nach dieser Inkrementierung geschieht Vorgang über die beiden Threads. Und in diesem Beispiel wir immer noch nur mit x plus 1 übrig, weil sie zunächst den gleichen Wert gesehen haben. Und so ist das irgendwie das Problem, das wir hier sehen. Offensichtlich sehen wir, dass es viel mehr als einmal passiert. Aber wir können das sehen, wenn diese Operationen in diesen Threads zunehmen. Und in diesem Fall müssen wir nur diese Zahl erhöhen, um sicherzustellen, dass wir unsere Chancen auf so etwas erhöhen. Wir geben diese Racebedingung ein, bei der der Wert von mehreren Objekten gleichzeitig zugegriffen wird, wobei jeder die Operation ausführt und dann den Wert überschreibt. Aber manchmal sind die Veränderungen, die wir bekommen, nicht die, die wir erwarten. Da zwei Threads beide x um eins inkrementieren. Und so bekommen wir hier keine Plus zwei, wir bekommen ein Plus eins. Offensichtlich ist das nicht immer der Fall, weil wir, weißt du, wir sind fast auf halbem Weg. Wenn ich mir diese Zahlen ansehe, schreien, also sind wir ungefähr auf halbem Weg. Aber offensichtlich passiert das ziemlich viel. Also, was können wir dagegen tun? Nun, da ist diese coole Sache, die ein Schloss genannt wird, und deshalb haben wir unsere Akte hier gesperrt. Also gehen wir in die Threading-Klasse und wir werden eine Sperre initialisieren. Nun, die beiden Methoden, die in dieser Gesetzesklasse verfügbar sind, die wirklich von Interesse für uns sind, werden gesperrt dot zu erwerben und Locke, Locke dot release, kommentieren diese aus. Das sind also diejenigen, die interessante Tests sein werden. Und was diese tun, ist, dass diese ein, im Grunde eine Sperre initiieren. An dieser Stelle ist dies eine Blockierungsoperation und nichts anderes kann passieren, während diese Sperre erworben wird. Also hat dieser Thread im Grunde das Schloss beansprucht. Und es sagt, als ob ich jetzt laufe, bis es es freigibt oder tatsächlich bis ein anderer Thread diese Sperre freigibt, dann nichts, was wir diesen Rennbedingungen nicht mehr begegnen können. Was also in diesem Fall passiert, ist Bedrohung. Die Bedrohung wird beginnen und es wird die Gegenvariable lesen. Aber der erste Thread wird beginnen und es wird sagen, Oh, ich bin Kehle ist, Thread verriegelt. Und dann wird es die Zählervariable lesen. Es wird es um eins erhöhen. Und dann ist es irgendwie sagen, Schloss loszulassen. Und dann werden wir einen anderen Thread haben , der auch sperren wird. Und dann wird es Ihnen das Ergebnis hier oben sehen, das x plus 1 ist. Und dann werden wir x plus 1 plus 1 haben, was x plus 2 sein wird. Und dann lassen wir das Schloss wieder los. Nun, offensichtlich, in diesem Fall, brechen wir irgendwie einen Teil der Parallelität, die uns zur Verfügung stand und irgendwie sequentielle Operationen erzwingen. Nun, offensichtlich wollen wir nicht ständig alles sperren , weil wir sonst nicht viel Nutzen gewinnen werden. Aber wirklich wieder, wenn Sie darüber bis zum Anfang nachdenken, verwenden wir Threading, hauptsächlich wenn wir Netzwerk-IO-Operationen blockieren. Also, wenn zwischen Netzwerk-Roundtrips viel Zeit verbracht wird, und wir wollen nicht nur im Leerlauf sitzen und auf eine Antwort warten. Das ist, wenn das Threading wirklich für uns gedeihen wird. In diesem Fall, wenn wir Operationen lokal durchführen, können wir die Sperre verwenden, um sicherzustellen, dass unsere Operationen konsistent sind und dass wir dort keine Race-Bedingungen treffen. Und dann wirklich wieder, der Punkt der Drosselung wird mehr in Richtung Netzwerk-IO sein. Seien Sie also offensichtlich nur bewusst, welche Auswirkungen Sie haben werden, wenn Sie Sperren verwenden. Aber gehen wir weiter und sehen das in Aktion. Also, was wir jedes Mal tun werden, bevor wir den Wert erhöhen, weil wir sagen, Lockdown erwerben. Und danach werden wir dieses Schloss loslassen. Also lasst uns weitermachen und das noch ein Mal ausführen. Und da gehen wir, wir bekommen das erwartete Ergebnis. Jetzt. Es gibt also eine Methode, die ich empfehlen würde, hier zu verwenden, obwohl ich denke, dass es ein wenig sauberer ist , dann sperren Sie, dass erwerben, sperren und loslassen. Denn wenn Sie kaufen anrufen, müssen Sie nur daran denken, auch Release anzurufen. Andernfalls werden Sie auf Probleme stoßen. Also lassen Sie uns das in einem kleinen Maßstab sehen. Und lassen Sie uns das laufen. In Ordnung. Also bin ich mal fertig, weil wir das Schloss nicht loslassen. Also haben wir im Grunde eine Sperre erworben und auf nichts anderes kann laufen, bis diese Sperre durch etwas freigegeben wird. Also werde ich das unterbrechen. Offensichtlich wollen wir das nicht vergessen. Der einfachere Weg, wie wir dies in Python tun können, ist die Verwendung des Context-Managers. Was wir sagen können, ist stattdessen, mit Locke, werden wir den Zähler um eins erhöhen. Also, was das tut, ist alles in diesem Gedankenstrich hier. Also klopfen Sie ein. Und du schließst ein. Alles in diesem Einzug wird hier innerhalb des Block-Punkt-Akquisition sein und dann die Freigabe gesperrt. Sobald wir aus diesem Gedankenstrich gehen, wo im Wesentlichen hier Loc Dot Release aufgerufen wird. Und gleich zu Beginn dieses Nnd, werden wir Laptop erwerben nennen. Aber dieser Weg ist offensichtlich ein bisschen sauberer weil wir das eigentliche Release nicht nennen müssen. Wir müssen nicht sicherstellen, dass wir sie nicht vergessen, weil das problematisch sein kann, besonders wenn Sie Programme haben, die ohnehin für eine Weile laufen werden. Und es dauert eine ganze Weile, um herauszufinden , dass Sie tatsächlich vergessen haben, das Schloss zu lösen. Stattdessen können wir einfach den Kontextmanager verwenden und mit Sperre sagen. Und dann wird alles hier drin zwischen diesem Schloss sein , das am Anfang erworben und eingesperrt ist oder zumindest am Ende. Und wir müssen uns keine Sorgen machen , dass wir vergessen haben, das Schloss zu lösen. Und damit wir sehen können, gehen wir auch zurück zu den zehn zu den sechs, die wir bei vier waren. Hier sollten wir auch die Formel bekommen, die wir erwartet haben. Dies ist also nur eine wichtige Sache zu beachten, da wir zuvor Warteschlangen für alles verwendet haben, was threadsicher ist. Aber manchmal, wenn Sie andere Dinge tun, besonders wenn Sie auf gemeinsame Variablen zugreifen, kann es dort Probleme geben. Denken Sie also darüber nach, wie Ihr Programm interagiert. Und wenn Sie Schlösser verwenden müssen und wenn Sie wissen, dass Sie in ihnen sind. Wenn Sie ein Programm geschrieben haben, in dem Sie möglicherweise tatsächlich auf eine Race-Bedingung stoßen können, denken Sie daran, dass das Sperren ein wichtiges Werkzeug sein wird um sicherzustellen, dass Sie tatsächlich die richtigen Ergebnisse erhalten, die Sie erwartest. 16. Multiprocessing: In Ordnung, jetzt, da wir eine Menge Sachen über Threading gesehen haben, lassen Sie uns weitermachen und einen Blick auf Multiprocessing werfen. Nun, zuerst möchte ich nur noch einmal ein einfaches Threading-Skript ausschreiben. Und dann habe ich eigentlich schon meinen Aktivitätsmonitor geöffnet damit wir die CPU-Auslastung ein wenig überwachen oder überwachen können. Und dann werden wir sehen, wie sich das ändert, wenn wir zur Multiprocessing gehen. Also werde ich von einem Threading sagen, ich werde Thread importieren. Wir werden hier eine Funktion haben, dass es nur überprüfen Werte in der Liste. Und es wird in einigen Listen aufnehmen, wir werden das einfach x nennen, und was es hier tun wird, ist, dass es eine Schleife haben wird. Wir werden sagen, für mich in Reichweite. Und lassen Sie uns zehn mit der Macht von acht tun, also 100 Millionen. Und wir werden nur überprüfen, ob ich ein X bin, und dann werden wir ein paar Threads erstellen. Also werden wir sagen, die Anzahl der Threads wird vier sein. Und wir werden unsere Threads-Liste hier haben. Wir werden es im Auge behalten. Und ich werde für mich im Bereich der Anzahl der Threads sagen, wir werden den Thread erstellen. Wir werden es haben. Die Zielfunktion ist dieser Prüfwert in der Liste. Und die Argumente, die wir ihm zur Verfügung stellen werden, werden die Liste sein, die wir verwenden wollen. Also sagen wir Vergleichsliste. Es wird gleich 1, 2, 3 sein. Geben Sie das als Eingabe an. Was wir also tun werden, ist, dass wir nur vier verschiedene Threads überprüfen werden, die über 100 Millionen Werte schleifen , um zu sehen, ob einer dieser Werte in diesem Thread sind. Also im Grunde nur einige CPU-Operationen ohne Netzwerkkomponenten. Und natürlich wollen wir diese Threads an unsere Liste anhängen, wo wir sie verfolgen. Und ich werde für tn Threads sagen, wir werden unsere Threads starten und wir werden für 10 Threads sagen, dann werden wir auch beitreten oder Drohungen. Und lassen Sie uns auch nur Zeit hier importieren. Und kurz bevor wir anfangen, sagen wir, dass die Startzeit zeitlich begrenzt ist. Und dann sagen wir, dass alles gedauert hat. Wir machen time.Deltatime minus Startzeit, Sekunden. Okay, also was wir hier getan haben, ist nur alles grundlegende Threading-Programm. Wir beginnen und schließen uns unseren Threads an, natürlich, wie wir in letzter Zeit viel abgedeckt haben. Und wir haben nur die einfache Liste, die drei Werte enthält , und für vier verschiedene Threads gehen wir nur in jeder Threadschleife über. Also werden wir eine Menge wiederholen, wiederholen Operationen tatsächlich, für jeden von ihnen werden wir nur überprüfen, ob der Wert darin liegt. Und dann werden wir die ganze Operation nur Zeit, um zu sehen, wie lange das alles dauert. Also werde ich hier einfach unsere Hauptfunktion starten. Und wenn wir zu unserem Aktivitätsmonitor gehen, dann können wir sehen, dass es natürlich eine kleine Spitze geben wird, was wir erwarten würden. Weil offensichtlich etwas funktionieren wird. Wir können tatsächlich sehen, dass unser Python Prozess hier gerade Arbeit macht. Und es wird ein bisschen Zeit brauchen, um all das zu beenden. Aber hoffentlich sollte es bald enden. Alles klar, also dauerte es ungefähr 33 Sekunden und wir können sehen, dass unsere CPU ein Jubel ist, nicht super signifikant, natürlich, ein bisschen offensichtlich über den Standardwerten, die wir haben, aber wir können im Allgemeinen sehen, wie lange es dauerte. Da wir also keine Netzwerkkomponenten haben, passiert eine Menge von diesem Zeug nacheinander, ähm, weil wir keine wirklich Netzwerkkomponenten haben. Lassen Sie uns jetzt, anstatt Threading zu verwenden, gehen wir weiter und verwenden Multiprocessing. Also werden wir von Multiprocessing sagen, wir werden Prozessklasse importieren. Nun ist das Schöne an der Verarbeitung und der Multiprocessing-Bibliothek, dass es tatsächlich sehr, sehr ähnlich ist , wie es in die Threading-Bibliothek geschrieben wird. Also, obwohl wir wirklich tun müssen, ist nur ändern Sie diese Namen wirklich für die Lesbarkeit. Das Einzige, was wir ändern mussten, war dieses Ding hier. Und jetzt werden wir stattdessen Multiprocessing verwenden. Also, was wir tun werden, ist, dass wir es, und lassen Sie uns aktualisieren, um es ist nicht mehr Anzahl Threads, es ist die Anzahl der Prozesse. Wir werden vier separate Prozesse erstellen. Dann fangen wir sie an, genau wie wir es vorher getan haben. Wir werden warten, bis sie fertig sind, genau wie wir es vorher getan haben. Wir liefern hier die Argumente, genau wie wir es vorher getan haben. Und die Funktion, die wir aufrufen, hat sich auch nicht geändert. Also machen wir im Grunde genau das Gleiche, aber jetzt verwenden wir Multiprocessing. Also lasst uns weitermachen und das laufen. Und ich werde hier unseren Aktivitätsmonitor öffnen. Und jetzt können Sie plötzlich sehen, dass es Spike. Und dann eine Sekunde hier, werden wir vier Prozesse haben. Und so ist das die Anzahl der Prozesse, die wir tatsächlich erstellt haben laufen. Was in diesem Fall passiert, ist, dass wir tatsächlich mehr als einen Kern verwenden. Also habe ich mehr als einen Kern auf meiner Maschine zur Verfügung. Aus diesem Grund können wir es mehr nutzen. Nun offensichtlich, wie wir hier sehen können, sind Speedup ist nicht genau proportional. Es gibt noch einige andere Faktoren. Eines der Dinge, die Sie gesehen haben, ist, dass die CPU-Auslastung für die vier Prozesse nicht die gleiche war wie die CPU-Auslastung, die einer der Prozesse hatte. Also denke ich, neben der Überwachung dieser, sagte es etwa 80 Prozent für jeden der Prozesse, während die Bedrohung tatsächlich fast 99. Etwas. So viel höhere Auslastung in diesem Sinne. Offensichtlich müssen wir auch Raum für andere Dinge lassen, die vor sich gehen, und unser Betriebssystem kümmern wir uns normalerweise darum, aber wir können sehen, dass wir immer noch eine Geschwindigkeitsverbesserung haben. Und die Menge an Geschwindigkeitsverbesserung, die wir von hier bekommen können hängt stark von der Anzahl der Kerne ab, die auf unserer Maschine verfügbar sind. Je mehr Kerne wir haben, desto mehr Prozesse können wir viele Prozesse erstellen, aber je mehr Prozesse wir gleichzeitig ausführen können, weil wir jeden von ihnen auf einem anderen Kern ausführen können. Und das ist wirklich das, was in diesem Fall passiert, ist jedes Mal, wenn wir diesen Prozess erstellen und starten, nehmen wir diesen Python Interpreter und wir beginnen im Grunde eine halbfrische Version auf einem anderen Prozess, so dass sie nicht widersprüchlich sind und dass es keine globale Dolmetschersperre gibt. Diese werden also nicht mehr zwischen dieser globalen Interpretersperre behindert. Und so ist der Vorteil, den wir daraus bekommen, die Beschleunigung. Nun, wie wir am Anfang gesprochen haben, ist Threading das, was wir verwenden werden, um es stark durch Netzwerk-IO begrenzt. Während Multiprocessing ist das, was wir tun wollen, begrenzt durch CPU-Auslastung oder CPU-intensive Prozesse, die in diesem Fall gibt es kein Netzwerk oder Warten oder irgendetwas. Es ist nur die CPU-Auslastung, die überprüft, ob ein Wert in einer Liste ist. Und so können wir sehen, offensichtlich, dass wir ein wenig bessere Ergebnisse aus unserer Multiprocessing. 17. Multiprocessing: Also natürlich können wir die Art und Weise, wie wir unser Programm hier machen, verbessern , indem wir die gleiche Arbeitslast wiederholen, etwas, das im Allgemeinen besser an die Multiprocessing-Funktion passen würde, wäre , unsere Arbeitslast auf verschiedene -Segmente. Sagen wir also, anstatt dasselbe für verschiedene Zeiten zu wiederholen, wollen wir einfach unsere Arbeitslast verteilen. Also werden wir hier einige zusätzliche Parameter haben. Das wird unser sein, wir werden es jetzt einfach AI nennen und dann werden wir eine Gesamtzahl von Prozessen haben. Also, was wir hier tun werden, ist, dass wir im Grunde ihr Auge und unsere Gesamtzahl von Prozessen nutzen werden, um dies in gleichgroße Eimer zu teilen. Also werden wir damit beginnen, im Grunde eine Untergrenze zu haben, die ich mal 10 zu den 8 sein wird. Und dann wollen wir auch eine Obergrenze haben, die abgeschaltet sein wird. Wir brauchen hier nicht einmal die Gesamtzahl der Prozesse, die ich plus ein Mal 10 zu den 8 sein wird. Und wir können diesen Wert sogar wegnehmen, eine abstrahierte in eine andere Variable extrahiert. Also werden wir sagen, dass die maximale Zahl, um zwei zu überprüfen, zehn bis zum achten sein wird. Und dann werden wir von unserer Untergrenze beginnen. Wir gehen in unsere Obergrenze. Also werden wir von I im Bereich unten nach oben sagen. Und zum Beispiel, wenn wir 0 hier haben, werden wir von 0 zu im Grunde gehen, naja, ein Mal das. Wir brauchen also eine Reihe von Prozessen. Da kam es ins Spiel. Anzahl der Prozesse. Und wir werden dies hier nur durch die Anzahl der Prozesse teilen und all dies in eine ganze Zahl konvertieren. Da unsere Bereichsfunktion hier verlangt, dass wir eine Ganzzahl verwenden. Also werden wir von gehen, der erste Schritt wird von 0 bis einmal diese Zahl geteilt durch die Anzahl der Prozesse sein. Es wird also 1 über 4 über 10 Millionen von 100 Millionen sein, was 25 Millionen sein wird. Und dann, wenn ich einer bin, gehen wir von 25 Millionen auf 50 Millionen. Es wird also 2 mal 25 Millionen sein. Und dann gehen wir und diese Schritte. Okay, also das Auge, das wir hier schon haben, ich bin von unserem Auge hier, die Anzahl der Prozesse, die Sie auch schon haben, denn das ist, was wir in dieser Bereichsschleife hier definieren. Was wir in diesem Fall tun, ist, nun, jetzt haben wir es gerade neu geschrieben, um es zu einem zumindest halbrealistischen Programm zu machen , um zu verstehen oder zu sehen, wie wir die Arbeitslast aufteilen können. Und wenn wir das wieder ausführen, dann offensichtlich in unserer Aktivitätsüberwachung oder zweitens, werden wir Ihre CPU-Last sehen, laden Sie hier Spike. Aber offensichtlich wird es viel kürzer sein, weil wir nicht das gleiche tun viermal, sondern wenn wir diese eine Operation auf vier getrennte Prozesse aufteilen. Also ja, im Allgemeinen wollen wir aber nicht nur diese Informationen haben, sondern wir wollen sie auch verwenden. Und so haben wir schon früher viel gesehen, dass wir die Warteschlange tatsächlich nutzen können , um Informationen weiterzugeben. Und wir können hier etwas Ähnliches tun. Wir können immer noch unsere Warteschlange verwenden und wir können eine Instanz der Klasse außerhalb erstellen. Und wir können das auch als Input bereitstellen, wie wir es hier haben. Und vielleicht ist die Information, die wir weitergeben möchten, ein jeder Bucket, wie viele Werte in unserer Liste sind und wie viele Werte nicht in unserer Liste sind. Also werden wir eine Variable haben, die Anzahl von Treffern hat, nur 0 sein wird. Und dann werden wir nur sagen, wenn x, wir werden erhöhen oder Anzahl der Treffer um eins. Und dann ganz am Ende werden wir diesen Wert zusammen mit unteren, oberen und einer Reihe von Treffern in die Warteschlange setzen . Auf diese Weise können wir einige Verarbeitung durchführen. Wir können die Informationen der Ergebnisse, die wir verarbeiten, tatsächlich nutzen. Also werden wir nur in jedem Bucket-Bereich überprüfen , wie viele unserer Variablen tatsächlich in dieser Liste sind. Wir werden das in eine Warteschlange stellen. Und dann wollen wir hier gegen Ende auch einfach fertig in die Warteschlange stellen. Und dann werden wir nur eine einfache while-Schleife haben, die während sagen wird. Und dann werden wir sagen, v ist gleich Q Punkt bekommt. Wenn v gleich getan ist, werden wir ausbrechen. Ansonsten haben wir unsere untere oder obere Anzahl von Treffern und Veeam. Und wir werden sagen, zwischen unteren und oberen, wir haben die Anzahl der Treffer Werte in der Liste. Okay, also lasst uns das noch mal laufen. Und wieder in unserem CPU-Diagramm können wir hier die kleine Spitze sehen. So können wir sehen, dass wir ein paar gute Informationen haben. Also zwischen, in diesem Fall, 0 bis 25 Millionen, haben wir drei Werte in der Liste, offensichtlich, weil wir 123 in der Liste haben. Und dann zwischen den anderen haben wir nicht viel Information. Der Sinn dieser Lektion ist also, dass wir sehen können dass wir Q weiterhin auf die gleiche Weise verwenden können, wie Sie es zuvor verwendet haben, aber wir können Informationen über und Prozesse oder verschiedene Threads weitergeben , wie wir es zuvor getan haben. Aber jetzt wird es zwischen verschiedenen Prozessen sein und das da drin verwenden. Und hoffentlich können Sie sehen, dass wir Prozesse nutzen können, um die Arbeitsbelastung grundsätzlich zu verteilen. Offensichtlich ist das Beispiel, das wir hier haben, ein sehr vereinfachtes Beispiel. Aber wir sind in der Lage, immer noch eine anständige Menge an Zeit zu sparen, anstatt ihre serielle Ausführung zu verwenden, indem wir einfach alles gleichzeitig tun. Oder sogar Threading, wo es im Grunde dasselbe sein wird , weil wir so CPU-intensiv sind, die Anzahl der Kerne, die wir auf unserer Maschine zur Verfügung haben, mehr nutzen konnten. Und tatsächlich nutzen Sie mehr von unserer CPU, um uns zu helfen, diese Berechnungen schneller abzuschließen. Nun, das ist wichtig für einen, wenn Sie Sachen auf Ihrem eigenen Computer ausführen, nur schneller fertig werden wollten und Sie viele Ressourcen haben, die nur im Leerlauf sitzen. Dies kann Ihnen natürlich helfen, von Programmen zu sprechen, aber auch wenn Sie Anwendungen bereitstellen und zusätzliche CPU-Ressourcen zur Verfügung haben, wenn Sie diese Ressourcen nicht nutzen, werden sie einfach im Leerlauf sitzen und Sie werden dafür bezahlen Sie, aber Sie werden nicht wirklich Gebrauch von ihnen machen. Offensichtlich hängt es davon ab, wissen Sie, wenn Sie einen einzigen Kern auf was auch immer Sie bereitstellen, dann wird diese Multiprocessing nicht viel helfen , weil Sie immer noch nur den einen Kern zur Verfügung haben. Aber wenn Sie am Ende eine Maschine haben oder eine Bereitstellung haben, in der mehrere CPU-Kerne verfügbar sind. Sie möchten sicherstellen, dass Sie sie am besten nutzen können. 18. Multiprocessing: Also, bisher haben wir gesehen, wie wir Multiprocessing nutzen können, um uns dabei zu helfen einige unserer Arbeiten auf verschiedene CPUs zu verteilen. Und offensichtlich ist das Muster, das wir hier sehen, sehr ähnlich dem Threading-Muster, mit dem wir vorher ins Detail gegangen waren. Und Sie können wahrscheinlich schon erraten. Aber die Art und Weise, wie wir Klassenvererbung mit Threading und alles, was wir getan haben, als wir unsere Threading-Arbeiter erstellt haben, können wir dasselbe mit der Prozessklasse tun. So können wir von der Prozessklasse erben und wir können eine Start- und Join-Methoden innerhalb sowie ihre Run-Methoden definiert haben. Und wir können im Grunde nähern, ein Multiprozessor-Programm um Multiprocessing-Klassen zu erstellen , die alle von dieser Prozessklasse hemmen und erben, genau wie wir es getan haben, als wir alle Threading-Dinge durchgingen. Und wir werden diesen Weg nicht hinuntergehen, weil wir das schon zum Einfädeln gemacht haben. Und offensichtlich gäbe es eine Menge Wiederholungen, die wir untergehen würden. Seien Sie sich also bewusst, dass das, was wir zum Threading und die Ansätze, die wir in der Syntax verwenden, fast identisch mit Multiprocessing sein wird, außer anstatt die Thread-Klasse zu verwenden, verwenden Sie stattdessen den Prozess -Klasse hier. Also, was ich Ihnen jetzt zeigen möchte, ist manchmal, wenn wir ein Threading-Programm schreiben, vorher gab es eine Menge Netzwerk-IO und es kann Sinn machen, diese wie kompliziert Programme zu entwickeln, denn wir können Cues verwenden, um alle Zustand auf intern. Und während eine andere Threads für verschiedene Dienste verantwortlich sind , die alle Arten von Umgang mit der Netzwerklast dort. Aber manchmal, wenn wir Multiprocessing machen, haben wir unseren Workflow ausgeschnitten und anstatt alles neu zu schreiben, wissen wir einfach, oh, hier ist etwas, das ich optimieren möchte. Und offensichtlich können wir dasselbe mit Threading machen , wenn wir eine kleine Komponente haben, in der wir so sind, oh, hier ist eine Menge Netzwerk-Zeug, die ich im Grunde optimieren kann und wissen Sie, anstatt zu warten und serialisiert, Ich kann einfach all diese Dinge und im Grunde die Hälfte aller Threads tun , so dass das Warten fast gleichzeitig geschieht. Aber für die Verarbeitung möchte ich mich jetzt nur auf diese Komponente konzentrieren. Und anstatt die einzelnen Prozesse wie diesen zu erzeugen, Warteschlangen zur Weitergabe von Informationen zu verwenden, möchte ich dieses Ding einfach sehr vereinfachen. Und was ich stattdessen tun will, ist, dass ich letztendlich zu dem Punkt kommen möchte, wo ich einfach unsere unteren und oberen Grenzen überschreiten kann. Und im Grunde irgendwie verteilt diese Arbeit für uns und dann einfach wie ein Return Value Center. Nehmen Sie das Q hier raus, um dieses Q rauszuholen. Also möchte ich keine Hinweise oder so verwenden. Grundsätzlich möchte ich nur eine Variable haben, die ich wie eine Ergebnisvariable haben kann, die etwas wie 30, 0, 0 sagen wird , und damit ich das einfach weiter verwenden kann. Bevor wir das tun, fangen wir mit etwas Einfacheres an. Wir werden nur mit dem grundlegenden Verarbeitungspool beginnen und wir werden eine viel einfachere Funktion haben , bei der wir einfach alles quadrieren werden. Also werden wir sehr viel zurück zu den Grundlagen gehen, zurück zu viel einfacheren Beispielen. Und wir werden erst eine einfache Funktion haben, die uns alles einordnen lässt. Denn schließlich, sobald wir das tun können, können wir dann kompliziertere Dinge in der Syntax machen, unterscheidet sich dot ein wenig davon, wie wir den Pool verwenden, weshalb ich zuerst mit diesem sehr einfachen Beispiel beginnen möchte , also dass wir nur sehen können, wie das funktioniert und wie wir dieses Ergebnis erzielen können. Dann können wir über die Aktualisierung oder Syntax gehen, so dass wir das immer noch nicht super kompliziert machen können , aber offensichtlich mehr Variablen und Sachen übergeben, die wir vorher hatten. Anstatt den Prozess zu verwenden, wir jetzt die Pool-Klasse verwenden. Jetzt mit der Pool-Klasse können wir es mit dem Kontext initialisieren. Also mit Pool als Pool oder als P oder was auch immer Sie wollen zieht ziemlich schön, weil, wissen Sie, offensichtlich ist ziemlich spezifisch. Wir können genauer sein und sagen wie Multiprocessing. Ich bin mir ziemlich sicher, dass hier irgendwo ein Tippfehler ist. Verarbeitungspool. Oder wenn wir nicht alles so ausschreiben wollen, können wir einfach wie und Leute schreiben, um ein bisschen spezifischer zu sein. Aber im Grunde werden wir nur diese Pool-Klasse initialisieren und sie dann im Kontext verwenden. So haben wir uns jetzt einen Pool von Prozessen zur Verfügung, die wir nutzen können. Also im Grunde, und wir werden in einer Sekunde darauf eingehen. Aber wir können hier tatsächlich die Anzahl der Prozesse definieren , die wir in unserem Pool zur Verfügung haben wollen. Zum Beispiel, wer hat die Nummer zwei? Und hier bedeutet das, dass wir das Potenzial haben, aber wir müssen es nicht unbedingt von zwei Prozessen verwenden, die uns zur Verfügung stehen, und wir können weiterhin Operationen durchführen und im Grunde diese Prozesse übernehmen. Aber sobald alle diese Prozesse aus dem Pool entfernt sind, sie uns nicht mehr zur Verfügung und wir müssen im Grunde warten, bis der Prozess an den Pool zurückgegeben wird, damit der nächste Vorgang ihn dann verwenden kann. Also wieder bei uns, wir sind im Grunde, sie werden einfach wie ein kleiner, man kann es sich vorstellen, wie ein kleiner kleiner Eimer. Und in diesem Eimer haben wir eine Reihe von Gegenständen zur Verfügung. Und wir können aus dem Eimer nehmen. Und sobald der Eimer leer ist, müssen wir warten, bis jemand den Gegenstand zurücklegt, den er herausgenommen hat. Und wenn etwas wieder im Eimer ist, können wir es wieder rausnehmen. Moment haben wir also einen Pool der Größe zwei, was bedeutet, dass wir zwei Prozesse zur Verfügung haben, die wir verwenden können, was im Wesentlichen bedeutet, dass wir für den Kurs verwenden können, da jeder Prozess einen neuen Kern hervorbringt. Also, was wir hier tun werden, ist, dass wir eine neue Methode verwenden werden. Wir werden unsere Multiprocessing cool verwenden. Und darauf werden wir diese Kartenmethode verwenden. Und hier werden wir die Funktion setzen, die wir verwenden möchten. Das wird also der Platz sein. Und dann werden wir auch unsere Eingabevariablen hier zur Verfügung stellen. Und wir werden all dies in einer Ergebnisvariablen speichern. Und wir können die Zeitkomponente hier herausnehmen, da wir das nicht mehr verwenden. Und lassen Sie uns einfach voran gehen und unser Ergebnis ausdrucken. Dies kann nicht einfach unsere Hauptfunktion ausführen. Ok? Also im Grunde haben wir genau das bekommen, was wir erwartet haben, das heißt, wir nahmen unsere Eingabeliste hier und wir bekamen das Quadrat jedes Wertes. Aber jetzt ist das Interessante, was wir bei uns haben, dass wir in der Lage sind, diesen Pool zu nutzen und wir in der Lage sind, diese Kartenmethode auf dort anzuwenden. Und wir werden nur, es wird im Grunde auf jede einzelne Komponente anwenden. Es wird also eins nach dem anderen durchlaufen. Aber wir werden die gleiche Struktur zurückbekommen, aber mit unseren Werten intern aktualisiert, obwohl wir nur mit einer Variablen arbeiten, können wir dies zurückgeben und im Grunde unser neues Ergebnis erhalten, das unsere Originalliste hier auf unseren Vergleichslisten an dieser Stelle. Aber es wird quadratisch sein. Also wird jeder einzelne Wert hier quadriert sein. Nun, dieser Wert, offensichtlich, kann es von der Maschine abhängen, die Sie auslaufen. Manchmal können Sie nur eine CPU verwenden, da Sie nur eine CPU zur Verfügung haben. Manchmal können Sie vier oder sechs oder acht oder 16 oder wie viele Sie auf Ihrer Maschine zur Verfügung haben. Wie können wir dieses kleine bisschen besser machen, damit es sich tatsächlich an die Maschine anpassen kann, auf der es läuft. Nun, es gibt diese coole Funktion, die wir als CPU-Anzahl importieren können. Und die CPU-Anzahl, wie Sie vielleicht erraten haben, wird uns nur die Anzahl der CPUs geben, die wir zur Verfügung haben. Also, was Sie tun können, ist, können Sie sagen, Anzahl der verfügbaren CPUs. Es wird nur sein, und wir werden nur unsere CPU-Anzahl aufrufen. Also, um das einfach auszudrucken. Und Sie können meine Maschine sehen, für die sie schießen wird, da ich vier Kohlenstoffe zur Verfügung habe. Dies kann jedoch je nach Maschine, auf dem Sie laufen, unterschiedlich sein. Aber vielleicht ist die Anzahl der CPUs, die Sie verwenden möchten , um eins kleiner als die Anzahl der verfügbaren CPUs. Denn wenn Sie alle Ihre Kerne verwenden, dann gibt es, wissen Sie, alles wird verwendet werden. Und so gibt es vielleicht nicht genug CPUs, um andere Dinge weiterzumachen. Andere Betriebssystemprozesse, zum Beispiel. Also im Allgemeinen, was Sie tun möchten, ist, dass Sie sagen können, dass die Anzahl der zu verwendenden CPUs unsere CPU-Anzahl minus eins sein wird. Aber in dem Fall, wo wir eigentlich nur einen Kern haben, wollen wir sagen, in Ordnung, nun, es wird das Minimum sein. Also werde ich nur gedacht, das Maximum zwischen einem und der Anzahl der verfügbaren CPUs minus1. Und dann können wir das hier benutzen. So kann ich in diesem Fall beispielsweise die Anzahl der verwendeten CPUs ausdrucken. Und jetzt werden wir drei zeigen, da es der Maximalwert zwischen 14 minus eins sein wird, das ist drei. Der Maximalwert zwischen diesen beiden wird also drei sein. Aber in dem Fall, wo wir nur eine CPU haben, also sind wir, ist dieser Wert eins. Wir werden stattdessen den Standardwert verwenden. Da wir offensichtlich noch etwas tun wollten. Auf diese Weise können wir sagen, in Ordnung, also abhängig von der Maschine, auf der wir laufen, können wir die Anzahl der verfügbaren CPUs sehen. Und dann können wir unsere gepoolte Größe haben, dass viele Prozesse für uns zur Verfügung stehen, um daraus zu ziehen. Und dann können wir diese Eingabeobjekte in die Funktion abbilden, die wir dafür verwenden möchten und dann diese einfach wirklich schönen Rückgabewert erhalten , den wir einfach weiter verwenden können. Also, anstatt dieses Müsli zu tun. Also wir iterieren und wir sagen k für mich im Bereich, wie lang oder Liste ist. Und dann gehen wir zum Quadrat und wir werden das in eine neue Liste setzen. Wir werden, wir werden unseren Wert aktualisieren, je nachdem, welcher auch immer, und dann weiter verwenden, so. Wir können einfach diesen Multiprocessing-Pool verwenden und diese Werte grundsätzlich unserer Funktion zuordnen und nur die aktualisierten Rückgabewerte erhalten, damit wir dies weiter verwenden können. Weil diese, diese Dysfunktion parallel passieren kann , weil es offensichtlich nicht von irgendetwas anderes um ihn herum abhängt. Und damit können wir skalieren, verwenden, um bestimmte Teile unseres Codes, die nicht unbedingt ein vollständiges Refactoring benötigen, sehr schnell zu beschleunigen , wie wir es mit Threading gesehen haben. Aber weißt du, nur eine kleine Linie hier könnte uns helfen, einen Großteil der Arbeit zu verteilen. Und dann können wir einfach auf unsere regelmäßige Weise weitermachen. 19. Multiprocessing: Alles klar, jetzt wirst du dich wahrscheinlich fragen, okay, wie kann ich mehrere Argumente übergeben? Wie kann ich so etwas machen? Und ich möchte x tun, aber ich möchte x auf die Macht von y so tun. Und ich möchte sagen, wissen Sie, unser neuer Leistungswert wird drei eigene sein. haben Sie vielleicht gedacht. Ich werde nur dieses zusätzliche Argument hier reinbringen, und das wird sich darum kümmern. Leider nicht. Und ich zeige dir, was passieren wird, aber ich muss das rückgängig machen. Sonst werden wir hier auf ein anderes Problem stoßen. Aber wenn wir dies ausführen und wir uns die Ausgabe ansehen, übergeben wir jetzt nicht mehr die einzelnen Werte in der Liste hier, sondern wir übergeben die Liste selbst. Also iterieren wir über jedes Element hier und übergeben das als Eingabe. Also, wenn wir y hier setzen, werden wir nicht die Ergebnisse bekommen, die wir wollen, unabhängig davon, ob wir es haben. Und sehen Sie hier, sind wir immer noch anrufen, wir drucken es nicht aus, weil unsere Funktion tatsächlich bereits fehlschlägt, weil wir ein zusätzliches Argument dafür vermissen. Und selbst wenn wir so etwas tun, wird keiner von ihnen für uns arbeiten. Wie können wir diesen zusätzlichen Parameter hier zur Verfügung stellen? Nun, wir werden ein Python Paket namens func tools verwenden, das bereits mit Python vorinstalliert ist. Und von hier aus werden wir eine Methode namens partiell importieren. Jetzt teilweise wird es uns erlauben, teilweise definierte Funktionen zu erstellen. So können wir sie teilweise anrufen, aber sie werden nicht vollständig angerufen. Aber wir können uns bereits einige der Parameter vorab zur Verfügung stellen und dann können wir sie später verlieren. Nun, um dies zu tun, denn die Art und Weise, wie wir Parameter bereitstellen werden , wird in einer bestimmten Reihenfolge sein. Und so wollen wir sicherstellen, dass wir den Parameter belassen, der im Grunde die Variable sein wird, die sich bis zum Ende ändern wird. Also werde ich eine Teilfunktion mit der partiellen Methode erstellen. Ich werde dieses Quadrat hier haben. Und der Wert, den ich für y will, wird unsere Macht hier sein. Jetzt kann ich diese Teilfunktion in der Map-Methode verwenden und ich kann all das Zeug wegnehmen. Jetzt wird unsere Karte einfach eins nach dem anderen durchlaufen, und es wird diese Funktion hier aufrufen. Diese Funktion ist bereits teilweise definiert, indem man die Quadratwurzel-Methode aufruft und diesen ersten Parameter bereitstellt, wie folgt. Wenn wir das jetzt ausführen, werden wir alles gewürfelt bekommen, denn das haben wir hier. Offensichtlich können wir das alles in die Macht von vier ändern, wie wir es hier getan haben. Und wir können dies auch für zusätzliche Parameter wie Addition, Komponente erweitern. Und sagen wir, wir wollen alles in der Macht von drei haben. Und dann wollen wir eine zusätzliche Komponente haben, und das wird 2 sein. Das werden wir hier zur Verfügung stellen. Also werden wir das einfach auf das Ergebnis am Ende hinzufügen. Also, wenn ich das mache, dann werden wir alles gewürfelt bekommen und dann werden wir ein Plus zwei haben , das von diesem Tippfehler hier kommt. So können wir sehen, ob wir die Map-Methode verwenden wollen und wir wollen zusätzliche Variablen in hier haben. Wir können das leider nicht einfach in ein Tupel oder eine Liste verwandeln und dann denken, Oh ja, alles wird darüber hinausgehen. Leider funktioniert die Kartenmethode nicht mit dem Multiprocessingpool. Aber wenn wir feste Variablen haben, die wir bereits vorher definiert haben , wollen wir nur hier zur Verfügung stellen. Und unsere letzte Komponente hier wird die Sache sein, die sich ändern wird. Dann können wir diese partielle Methode aus den Funk-Tools verwenden. Und hier können wir unsere Funktion teilweise definieren. Und dann können wir es mit den verschiedenen Komponenten füllen, die wir hier haben, um die Funktion irgendwie aufzurufen, und es ist vollständiger Weg und wirklich die Ergebnisse zu erhalten , die wir wollen, während wir bereits einige der Argumente übergeben haben. 20. Multiprocessing: In Ordnung, also haben wir vorher gesehen, dass wir zusätzliche Argumente bereitstellen könnten , indem wir diese partielle Methode in unseren Func-Tools verwenden, eine Bibliothek, die wir importiert haben. Und wir waren in der Lage, Funktionen teilweise zu definieren oder teilweise die Komponenten von Funktionen bereitzustellen. Und dann können wir unsere Map-Methode hier verwenden, um diese verbleibende Komponente bereitzustellen. Aber was, wenn wir keine festen Komponenten wollen oder haben, sondern stattdessen eine andere Entität haben wollen, zum Beispiel eine machtlose. Und hier wollen wir das erste Element hier haben, zum Beispiel die Macht für das zweite auf die Macht 5 und das dritte auf die Macht von sechs. So wissen wir bereits, was wir bieten wollen. Wie können wir dies auf eine Weise tun, die nicht so ist, sondern idealerweise nur in der Lage ist, das direkt bereitzustellen und diese Berechnungen durchzuführen. Also werde ich hier schnell aufräumen, dieses Zeug entfernen und auch nur einige Reorganisation unserer Funktionsparameter vornehmen. Nur um es ein bisschen mehr zu haben, sollte es sein zu lügen. Ein bisschen leichter zu sehen. Und wir brauchen diese partielle Funktionsdefinition auch hier nicht. Was wir also tun wollen ist, oder was wir tun können, ist, dass wir eine Methode namens Sternkarte verwenden können. Jetzt in unserer Sternkarte können wir hier eine Eingabe bereitstellen, die folgendes hat, das sieht so aus. Und dann können wir im Inneren zusätzliche Elemente bereitstellen , über die wir iterieren können, wenn wir wollen. Und all diese Elemente können wir dann als einzelne Parameter an unsere Funktion übergeben. Also zum Beispiel, in unserem Fall, was wir tun wollten, ist, während ein erstes Element, das wir passieren wollen, 1 und 4 sein würde, da das unser x und y sein wird. Das zweite wird 25 sein, und dann das dritte hier ist wird 36 sein, da wir diese beiden zusammen zur Verfügung stellen und diese dann als unsere x und unsere y Parameter zur Verfügung stellen wollen . Und wenn wir dies als Eingabe zur Verfügung stellen, dann im Grunde, was wir bekommen werden, ist die Ausführung wie diese. Und offensichtlich verwenden wir, wer der Multiprocessing-Pool noch. So werden wir in der Lage sein, verschiedene Farben zu verwenden, um uns zu helfen, dies zu tun. Also wirklich, was wir jetzt tun müssen, ist, dass wir diese beiden Listen so zusammenfügen müssen , dass wir dieses Format hier bekommen können. Und dann können wir das als Input zur Verfügung stellen. Also werden wir unsere vorbereitete Liste haben, die nur eine leere Liste sein wird, mit der wir anfangen werden. Also werden wir nur über die Länge dieser Liste iterieren. Und so werden unsere Elemente, die wir hier hinzufügen wollen, einfach sein, wir wollen hier haben, unser erstes Element wird immer aus unserer Vergleichsliste kommen. Es wird das erste Element hier sein. Und das zweite Element, das wir wollen, wird es aus unserer Energieliste kommen, die wir 0 setzen können. Wir wollen die i-te Komponente. Und so können wir das letzte Mal ausdrucken, dass wir einige Listen einfügen, die als Eingabe verwendet werden sollen. Ich werde nur das sein. Und dann können wir das erledigen. Und dann werden wir tatsächlich in der Lage sein, jedes der Elemente im Inneren als einen der Parameter hier bereitzustellen . Also lasst uns voran gehen und diese Schleife laufen. Ich habe hier einen Tippfehler. Und ich habe auch vergessen, zu aktualisieren. Das hebt sich hier drin. Also lasst uns das noch einmal versuchen. Da gehen wir hin. Dies ist also die Liste, die wir als Eingabe verwenden. Und wir können sehen, dass unser x und unser y sind also unsere Funktionsparameter, die wir übergeben. Das wird also dein x und unser y sein, unser X und unser Y, oder X und unser Y. Also machen wir eins zu der Macht vier, das ist 12 auf die Macht von fünf, die 32 sein sollte, und 3 auf die Macht von sechs, die sollte 729 sein. So können wir sehen, dass wir mit einer Sternkarte tatsächlich mehrere Eingabeparameter zur Verfügung stellen können, besonders wenn Sie wissen, dass sich diese ändern werden. Es ist nur wichtig, sicherzustellen, dass wir diese Art von Struktur haben , damit wir diese weitergeben können. Und dann werden die Elemente oder die Werte, die wir in unsere Funktion übergeben in der Reihenfolge sein, in der wir die Parameter in unserer Funktion hier haben. Und so sind wir tatsächlich in der Lage, mehrere Parameter zu übergeben. Also die Fledermaus, wir brauchen diese partiellen funktionalen Funktionsdefinitionen nicht zu verwenden, wenn mehr als eine unserer Variablen variiert. 21. Multiprocessing in der Liste in bestimmten Bereichen: Also kommen wir endlich zu unserer anfänglichen etwas CPU-intensiveren Funktion zurück , die wir benutzt haben, die nur überprüft wird, ob ein Wert oder wie viele Werte in unserer Vergleichsliste tatsächlich innerhalb eines bestimmten Bereichs liegen. So kann sagen, rufen Sie dies zum Beispiel, überprüfen Sie die Anzahl der Werte im Bereich. Und dann werden wir hier haben, um unsere Vergleichsliste zu sein. Und hier werden wir unsere unteren und oberen Grenzen haben. Und dann wollen wir die Anzahl Treffer verfolgen. Und dann wollen wir für mich im Bereich von unten bis zu unserer Obergrenze sagen. Wenn Augen und unsere Liste hier. Wir wollen das nur um eins erhöhen. Also ja, wir vermissen ein I hier und am Ende wollen wir einfach die Anzahl der Treffer zurückgeben. Also wieder, der Sinn dieser Funktion ist nicht wirklich, etwas mehr zu tun, außer etwas zu sein, für uns, nur ein bisschen mehr von einer rechenintensiven Aufgabezu simulieren einer rechenintensiven Aufgabe , weil es nehmen Sie sich ein wenig Zeit, um dies zu berechnen. Also die verschiedenen unteren und oberen Bereiche, die wir haben werden. Und wenn wir wollen, können wir einfach diese Bereichsregel angeben. Lassen Sie uns diese Unter- und Obergrenzen nennen. Und natürlich können wir diese beiden mit wie ein wenig for-loop erzeugen. Aber eigentlich, wenn wir uns nur in vier teilen, können Sie im Grunde sehen, was wir tun, ist, dass wir von 0 auf 25 Millionen gehen. Also wird es zehn bis zur Macht von sechs sein. Und dann gehen wir von 25 Millionen auf 50 Millionen mal zehn auf die Macht von sechs. Und dann werde ich das einfach kopieren. Und wir werden von 50 Millionen auf 75 Millionen gehen. Und schließlich wollen wir von 75 Millionen auf 100 Millionen gehen . Das werden also unsere Unter- und Obergrenze sein. Jetzt müssen wir es natürlich in diese Art von Format bringen. Stattdessen wollen wir in diesem Fall unsere Vergleichslisten für den ersten Eingabewert im Grunde wollen. Und dann wollen wir unser Unteres und unser Oberes hier. Und dann wollten wir auch diese oder die anderen machen. Also müssen wir immer noch ein bisschen beizutreten, wie wir es hier getan haben. Aber da wir hier nicht viele Werte haben, bin ich einfach einfacher, diese vier Werte und von Hand zu setzen. Aber natürlich können wir ein wenig for-Schleife schreiben, um diese Liste auch für uns zu füllen, vor allem, wenn Sie 50 oder ein 100 mögen oder sogar 10 oder 20 verschiedene Balance mögen wollten. Ja, jedenfalls, also müssen wir nur noch unsere Liste vorbereiten. Also werden wir hier unsere Vergleichsliste verwenden. Aber anstatt über diese Länge zu iterieren, werden wir dies im Grunde als eines der Elemente hier hinzufügen. Und so wird die Anzahl der verschiedenen Eingabewerte, die wir haben werden, tatsächlich die Listen sein, die Länge dieser Liste. Also wollen wir über die Länge dieser Liste iterieren. Hier möchten wir die vollständige Vergleichsliste hinzufügen. Und wir wollen auch die einzelnen Komponenten hinzufügen. Es wird also unser erster und unser zweiter Wert hier sein. Und dann werden wir dies als Input zur Verfügung stellen, um unsere Berechnungen durchzuführen. Also nochmal, was wir tun, ist, dass wir diese Liste nehmen und wir haben im Grunde unsere neue vorbereitete Liste, die so und so aussehen wird. Das ist genau das, was wir hier tun. Und dann wird diese Komponente hier unser erster Input sein , der eine Liste sein wird. Und dann werden die anderen unsere Unter- und Obergrenze sein. Also werde ich das natürlich rückgängig machen, weil das ist, was diese kleine Schleife hier als vier ist. Und dann gehen wir weiter und führen das aus. Und so können wir sehen, dass dies unsere Eingabeparameter hier sein werden. Jeder von diesen, wie wir in den Funktionsargumenten haben, wird dies unsere Vergleichsliste sein, unsere untere und obere Grenze. Und so können wir offensichtlich im ersten Bereich sehen, haben wir drei Elemente, die Seite enthalten sind, weil ihre Zahlen 123 sind. Und dann auf den anderen wurden alle 0 haben. Das ist also irgendwie der Vollkreis zurück zu dem, was wir mit vier angefangen haben, sorry, zum Beispiel für Multiprocessing, um uns zu helfen, dies zu tun. Und jetzt können wir unsere Startmethode in diesem Fall verwenden, um diese mehrere Eingabeargumente bereitzustellen, wie wir hier haben. Nun, eine Sache, die wir tatsächlich tun können, um die Syntax ein wenig zu vereinfachen, ist, anstatt die Listen so aufzulisten. Stattdessen können wir einfach diesen kleinen Asterix benutzen. Und was das tun wird, ist, dass es alle Werte hier drin auspacken wird. Sie können also sehen, ob ich das erneut ausführe, werden wir genau die gleichen Ergebnisse erhalten. Der einzige Unterschied besteht darin, dass ich jede dieser einzelnen Komponenten referenzieren muss , wie wir es hier getan haben. Dieser Stern wird es im Grunde entpacken und es wird all diese nehmen und sie als zusätzliche Eingabewerte nacheinander zur Verfügung stellen, genau in der Reihenfolge, in der wir sie hier haben. Das ist also nur eine kleine Abkürzung, die ich verwenden kann , anstatt dies zu verwenden, weil ich alle Elemente erhalten möchte. Aber wenn ich will, wissen Sie, 10, 20 oder 15, als würde es länger werden und es wird mühsam. Und wirklich, was ich tun möchte, ist, dass ich nur alle diese Werte hier haben möchte, aber ich will sie nicht in einem Tupelformat wie diesem. Ich möchte nur alle einzelnen Elemente nacheinander. Und die Art und Weise, wie ich das tun kann, ist, indem ich den Stern verwende , der jedes dieser Elemente im Inneren als individuelle Werte hier zur Verfügung stellt. Das ist also nur eine Kurzschrift, um diesen sauberer zu halten und es auch ein wenig schneller zu schreiben. 22. Einführung in das Schreiben von Asynchronen Programmen: Okay, also lasst uns jetzt einen Blick auf asynchrone Programme werfen oder wie wir ein asynchrones Programm schreiben können. Und das wird unsere dritte Option sein, die wir für Parallelität haben. Und Sie werden einen Punkt bemerken. Es wird wahrscheinlich ähnlich wie Threading aussehen, obwohl es wieder anders ist, weil wir bei asynchronen Programmen nur einen Thread haben, der ausgeführt wird, und wir haben auch nur einen Prozess. Also lasst uns voran gehen und einfach reingehen und sehen, was passiert. Das erste, was wir tun werden, ist, dass wir asynchrone IO importieren, was uns bei all dem helfen wird. Jetzt bin ich auf Python Version 3.7 und ich empfehle , dass Sie auch an mindestens Python-Version 3.7 arbeiten. Aber natürlich, wenn Sie auf einer späteren Version von Python sind, wird es besser sein, nur weil die asynchrone Bibliothek bis zu diesem Punkt ein wenig nicht experimentell war, aber sie hat sich sehr verändert. Und an diesem Punkt scheint es einen bestimmten Zustand zu haben, wie es funktioniert. Also würde ich nur allgemein empfehlen, stellen Sie sicher, dass Sie eine spätere Version von Python verwenden, wenn Sie möchten. Oder zumindest Python 3.7, was wieder auf dem ich gerade bin. So können wir asynchrone IO importieren und das sollte ein Standard-Python Paket sein. Und dann können wir anfangen, unsere erste asynchrone Funktion zu definieren. So können wir dies tun, indem wir nur eine normale Funktion haben. Zum Beispiel, wenn wir eine Art Schlaffunktion haben wollen , wo alles, was wir hier tun, ist schlafen, sagen wir fünf Sekunden. Wenn wir stattdessen asynchron tun wollen, dann würden wir vor hier das Schlüsselwort async setzen. Und dann hier statt den zeitgesteuerten Schlaf zu verwenden, würden wir tatsächlich eine Sync-iOS-Schlafmethode verwenden. Und wir werden in nur einer Sekunde ein bisschen mehr über die Argumentation sprechen. Aber im Grunde, was wir daraus bekommen, so werden wir eine asynchrone Funktion definieren. Jetzt müssen wir noch eine Sache hier tun, nämlich wir müssen tatsächlich auf diese Funktion warten , oder diese Co-Routine ist eigentlich das, was sie heißt. Und wirklich, was hier passiert. Und der gesamte Prozess der Verwendung von asynchroner Ausführung und Python ist, und wir werden sehen, wie dies in einer Sekunde zu tun ist. Aber wir beginnen etwas, das eine Ereignisschleife genannt wird. Und dann können wir hinzufügen, beginnen, Aufgaben hinzufügen oder Aufgaben planen mit dieser Ereignisschleife. Und dann innerhalb dieser Ereignisschleife werden Objekte aufgerufen oder Dinge haben, die Futures genannt werden. Und diese Futures stellen im Grunde etwas dar, das noch nicht zurückgekommen ist, aber etwas wird daraus kommen. Das klingt also etwas verwirrend, aber was passiert im Allgemeinen, wenn wir mehrere asynchrone Funktionen planen? Jeder von ihnen wird eine Zukunft bieten, die irgendwann beendet wird, oder sie werden eine Art von Kontrollpunkt erreichen. Und von diesem Punkt an können wir dann das nächste mit dieser Co-Routine machen. Das Ganze, was wir hier definiert haben, wird im Allgemeinen als Co-Routine bezeichnet. Und es sind die Dinge, die wir in unseren Event-Schleifen hinzufügen und planen. Nun, wenn wir weiter codieren, wird dies hoffentlich ein wenig intuitiver und wir werden nicht so in der Syntax von allem verloren gehen. Aber offensichtlich, weil wir nicht asynchrone Dinge durchlaufen, ist es wichtig, nur einige dieser Schlüsselwörter und den Anfang erwähnt und gesprochen zu haben, aber auch während wir weitermachen. Also, wenn wir das ausführen wollten, wenn wir gerade angerufen haben und es tatsächlich in asynchrone Schlaf umbenennen. Wenn wir nur einen Senkschlaf genannt haben. Schlafen Sie so. Leider wird es nicht wirklich laufen. Wir werden hier einen Fehler bekommen, der im Grunde darauf zusammenhängt. Nun, zum einen steht, dass das Coubertin nie erwartet wurde, was wir hier haben. Aber selbst wenn wir dieses await Schlüsselwort hinzufügen, wird es immer noch nicht funktionieren, weil wir gerade keine Ereignisschleife haben , die all dies verbraucht. Und abgesehen davon können wir das Schlüsselwort await nicht außerhalb einer Funktion verwenden , die nicht asynchron def ist. Also, wie können wir das Ding zum Laufen bringen? Wie können wir diese nackten Knochen zum Laufen bringen? Also werden wir eine neue Funktion erstellen, die unsere Hauptfunktion sein wird, die wir auch mit async def definieren werden. Und was wir hier tun werden, ist, dass wir auf die Reaktion unseres asynchronen Schlafes warten werden. Nun, die await Schlüsselwörter hier, weil wir diese Ereignisschleife haben und wir können mehrere verschiedene Co-Routine in dort geplant laufen. Im Grunde, was dieses Schlüsselwort erwartet, ist, dass es die Kontrolle zurück zu unserer Ereignisschleife gibt , um mit anderen Dingen fortzufahren. Also im Grunde sagt es dem Programm, dass wir an diesem Punkt sind, wir warten auf eine Antwort und bis wir diese Antwort haben oder bis wir etwas hier haben, das wir weitermachen müssen. Es hat wirklich keinen Sinn, mir alle Ressourcen zu geben , denn es gibt nichts, was ich tun kann, bis ich das bekomme. Das ist also in der Regel der Punkt eines Gewichts. Aber selbst wenn wir das haben, können wir Main Hulk immer noch nicht anrufen. Wie können Sie das Haupt zum Laufen bringen? Was wir also tun können, ist, dass wir diese asynchrone IO-Punktlaufmethode verwenden können. Und hier werden wir die Haupt-Co-Routine setzen, die wir ausführen wollen. Und das wird im Grunde die Ereignisschleife für uns starten. Und es wird den Verbrauch der Ereignisschleife beginnen und im Grunde den gesamten Prozess für uns übernehmen. Es gibt andere Methoden. Zum Beispiel können Sie eine laufende Ereignisschleife erhalten und Sie können bis zum Abschluss oder diese anderen Dinge, die spezifischer für die Ereignisschleife sind, ausführen . Aber wirklich nur die Verwendung von asynchronem IO dot Ron kümmert sich um all dieses Management für Sie und Sie müssen sich nicht wirklich um irgendwelche der Dinge auf niedrigerer Ebene kümmern. Das hier wird also unser Einstiegspunkt sein. Nun ist eine wichtige Sache zu beachten, dass wir nur eine laufende Ereignisschleife pro Thread haben können . Und standardmäßig werden wir dies nur auf einem Kern und einem einzigen Thread ausführen. Im Grunde bedeutet das, dass wir nur einen asynchronen IO-Punkt-Sprohlungsaufruf haben , der der Einstiegspunkt für unser Programm sein wird. Und natürlich können wir dies in die, wenn Name gleich main umwickeln. Um, also für die Ausführung der Hauptdatei hier, dann werden wir mit beginnen können in diese Ereignisschleife gehen. In Ordnung, also lasst uns das jetzt versuchen. Also führen wir das Programm aus und alles, was wir tun, ist asynchron für fünf Sekunden zu schlafen. Aber offensichtlich geht an diesem Punkt nicht viel anderes vor sich, weil wir nur eine Sache tun. Und selbst wenn wir die Kontrolle über die Ereignisschleife zurückgeben, was wir hier tun. Es läuft nichts anderes, es ist nichts anderes los, also gibt es nichts anderes, um während dieser Zeit weiter zu arbeiten. Also lassen Sie uns jetzt eine zweite Funktion hinzufügen, die eine asynchrone Funktion sein wird Hallo auszudrucken. Und alles, was das tun wird, ist, dass es ausgedruckt wird, wie der Name schon sagt. Hallo. Alles klar, was passiert jetzt? Wenn wir wie hier geplant? Und dann lassen Sie uns etwas extra drucken, um zu sehen, wo wir in unserem Programm sind. Also wirst du sagen, bevor du schläfst. Und dann können wir danach noch einen Druck abgeben. Hier. Wir werden nur nach dem Schlafen sein. Alles klar, was ist los? Wir haben, nun, wir schweben Einstiegspunkt. Also beginnen wir im Grunde die Ereignisschleife und wir starten das x oder die Planung seiner Haupt-Co-Routine. Dann gehen wir hier in diese Hauptroute Co-Routine. Und jetzt gehen wir zu unserer ersten Zeile, die auf die Antwort dieser asynchrone Schlaf-Co-Routine warten wird , die wir hier drin haben. Sobald wir hier reingehen, drucken wir vor dem Schlafen aus, und dann haben wir diesen Anruf erwartet. Was also mit dem await-Aufruf passiert, ist die Art und Weise, wie der Anruf nicht blockiert wird. Es ermöglicht die Ausführung anderer Co-Routinen. Es stoppt jedoch die Ausführung, in dieser Funktion weiter nach unten zu gehen. Also, und wenn wir das ausführen, werden Sie bemerken, dass wir in diese Funktion gehen und dann rufen wir vor dem Schlafen an. Und dann schlafen wir für fünf Sekunden. Und dann gehen wir in den Nachschlaf. Und nur dann gehen wir weiter zur zweiten Aussage hier. Leider können wir damit nicht überspringen und zur nächsten Sache gehen. Diese Erwartung ist im Grunde ein Haltepunkt in unserer Co-Routine, in unserer Programmausführung, wie speziell in dieser Funktion in dieser Co-Routine sind. Und das ist irgendwie, wo wir kurz zur Hinrichtung anhalten. Und es sagt im Grunde, oder die Funktion oder die Co-Routine an dieser Stelle sagt, ich brauche jetzt keine Kontrolle. Ich warte auf eine Antwort. Fühlen Sie sich frei, Sie auf andere Dinge zu tun. Und dann kann unsere Ereignisschleife weitergehen und andere Dinge tun. Und wenn diese Funktion bereit ist, kann es ein Signal geben, das sagt: Hey, ich bin bereit, fortzufahren. Und dann kann die Kontrolle zurückgegeben werden. Aber weil wir nur eine Haupt-Co-Routine laufen, und in diesen nennen wir Tumor-Cole-Routinen. Diese werden immer noch sequentiell ausgeführt und es gibt keine mehrere Co-Routinen gleichzeitig geplant werden. So dass, wenn wir diesen warten Anruf hier erreichen, können wir tatsächlich mit der Ausführung einer anderen Co-Routine fortfahren. Und wir werden uns im nächsten Abschnitt ansehen, wie das geht. Es gibt noch eine Sache, die ich Ihnen vorher zeigen wollte , wie können wir daraus Werte zurückgeben? Es wird also so sein, als hätten wir regelmäßige Funktionen. Also lassen Sie uns das von print hello umbenennen, um sie allein zurückzugeben. Und das wird stattdessen hallo zurückgeben. Und so, um das Ergebnis zu erhalten, genau wie bei einer regulären Funktion, nennen wir unsere Rückkehr hallo. Aber jetzt, weil es eine asynchrone Funktion ist, müssen wir darauf warten. Und sobald diese Funktion erledigt ist , erhalten wir hier den Rückgabewert. Und dann können wir es ausdrucken. Also wird es genau das Gleiche tun. Es ist nur hier. Wir drucken es nicht intern aus, sondern anstatt einen Wert von der Funktion wie folgt zurückzugeben, und Sie werden feststellen, dass der Hauptunterschied zu einer regulären Funktion die asynchrone und warten ist. Also könnten wir das Gleiche hier machen, so. Und das wäre nur ein regelmäßiger Funktionsaufruf. Und wir können den Wert von hier zurückgeben, wie wir es normalerweise tun würden. Aber das können wir nicht tun, wir können nur Co-Routinen warten. Das wird also einen Fehler für uns verursachen, wie wir in einer Sekunde sehen werden. Und etwas anderes, was wir auch nicht tun können, ist, dass wir es nicht können. Wenn wir dies entfernen und dieses ein Gewicht entfernen, können wir ein await Schlüsselwort innerhalb eines nicht und nicht innerhalb einer Co-Routine verwenden. Also müssen wir diese asynchrone Definition im Vordergrund haben, um intern warten zu können. Wir können also nicht await verwenden, ohne ein asynchrones def außerhalb davon zu haben. Und wenn wir eine asynchrone asynchrone def Definition haben, müssen wir auf die Antwort warten, da sonst im Grunde Sie hier ein Co-Routine-Objekt erstellen, aber es wurde nie geplant, es war nie weg, so dass es nie tatsächlich ausgeführt wurde, nie zur Ereignisschleife hinzugefügt wurde. Seien Sie sich also dieser Dinge bewusst, dass Sie, wenn Sie async verwenden, immer auf diese Antwort warten müssen. Und der Abwart-Anruf hier blockiert nicht. Es stoppt jedoch die weitere Ausführung der Funktion und gibt die Kontrolle zurück auf die Ereignisschleife, so dass andere Teams in der Zwischenzeit laufen können. Damit weiß ich, dass es ein bisschen verwirrend ist. Das erste Mal, dass wir das alles durchreden und es gibt einige seltsame Begriffe, die auftauchen. Aber während wir die nächsten Vorträge durchlaufen werden, werden Sie hoffentlich ein klareres Verständnis davon bekommen, wie das alles funktioniert. Und wahrscheinlich auch mit der Zeit wird dies für Sie ein bisschen komfortabler. 23. Asynchrone Aufgaben: Das nächste, was wir jetzt betrachten werden, ist, wie wir Aufgaben erstellen können , die, na ja, wir werden sehen. Das erste, was wir letztes Mal bemerkt haben, ist, obwohl wir hier asynchrone Funktionen verwenden, und wir können dies auch zurück zu asynchronen def wechseln und vielleicht einfach zu einer print hallo-Anweisung zurückgeben. So wie das hier. Wir drucken nur Hallo und Tunneling aus. Obwohl wir diese asynchrone Syntax verwenden, ist die Ausführung, die wir erhalten, immer noch im Wesentlichen synchron, da es nichts anderes gibt, zu dem das Steuerelement übergehen kann. Obwohl wir diese asynchrone Syntax verwenden und unser Steuerelement an die Ereignisschleife zurückgegeben wird. Es gibt nichts anderes im Zeitplan, das weitergehen kann. Und so gibt es nichts anderes, an dem gearbeitet werden kann, während wir auf eine Antwort warten. In ähnlicher Weise, wenn wir hier einen weiteren Schlafanruf hatten, nun, bemerken wir, dass wir immer noch diese synchrone Ausführung des Recyclings bekommen, die zu schlafen beginnt, fünf Sekunden schlafen wird. Und dann gehen wir zum nächsten Punkt. Und hier sind wir zum Schlafen. Wir warten hier auf die Antwort. Und dann, obwohl die Ausführung zurückgegeben wurde, Es gibt nichts anderes, was fortgesetzt werden kann. Und an diesem Punkt, obwohl die Ausführung der Ereignisschleife zurückgegeben wird, gibt es wieder nichts, was fortgesetzt werden kann, weil das einzige, was nicht fortfahren kann, die weitere Ausführung dieses Funktionsblocks, weil wir noch auf diese Antwort warten. Und es gibt nichts anderes, was so geplant ist, kann bearbeitet werden. Also im Allgemeinen, was wir haben können, ist, dass wir tatsächlich anfangen können, Aufgaben zu erstellen. So können wir mehrere Aufgaben in unserer Ereignisschleife haben , an denen gearbeitet werden kann, während Dinge erwartet werden. Also lassen Sie uns ein Beispiel dafür sehen. Lassen Sie uns eine Aufgabe erstellen. Und wir werden das tun, indem wir in eine Spüle gehen. Und wir werden hier nennen erstellen Aufgabe. Und ich werde diesen zweiten asynchronen Schlafanruf annehmen. Und ich werde die Aufgabe hinzufügen und hier. Und dann werde ich später auf die Aufgabe warten. Was also passiert, wenn wir eine Aufgabe erstellen, ist, dass wir diese Co-Routine grundsätzlich so planen, dass sie bearbeitet wird, wann immer es bequem ist. Aber bis wir es erwarten, gibt es kein Stoppen im Fluss unserer Co-Routine, um an diesem Punkt anzuhalten. Was wir an diesem Punkt bekommen, ist daran zu erinnern, bevor wir unsere beiden Schläfe hatten , die einer nach dem anderen passieren. In diesem Fall haben wir eine weitere Aufgabe hinzugefügt. Und wenn wir das wirklich erneut ausführen, werden wir jetzt sehen, dass wir zwei vor Schlafplätzen haben, die vor sich gehen. Und dann, oops, ich habe hier einen Syntaxfehler. Ich muss den Funktionsaufruf wegnehmen, weil es ein Objekt ist, auf das wir warten, keine Funktion oder eine Coworking-Methode, weil wir die Funktion bereits aufgerufen haben. Also haben wir nur einen Trainer, ein Objekt, das zu uns zurückkehren wird. Aber wie auch immer, wir warten noch darauf. Aber wir werden hier feststellen, dass wir jetzt einmal schlafen und jetzt wieder schlafen. Und dann beginnen wir das im Grunde zweimal und dann sind wir in der Zeitüberschreitung, und dann sind wir hinter unserem Schlaf. Wenn wir also das Zeitmodul importieren, während es vor der Ausführung immer noch sequentiell ist. So können wir hier eine Startzeit haben, die unsere Zeit sein wird.Deltatime. Wir können hier drucken. Die Gesamtzeit wird Zeit sein, Zeit minus Start. Wir werden also feststellen, dass unsere Hinrichtung jetzt nicht um die 10-Sekunden-Marke liegt, was wir hatten, als wir zweimal hintereinander geschlafen haben, sondern sich auf der 5-Sekunden-Marke befinden. Also haben wir diese zusätzliche Aufgabe erstellt. Dann, wenn wir in den warten Aufruf gehen, haben wir jetzt eine andere Co-Routine, die wir gehen können , wo eine andere Aufgabe, die auch ausgeführt werden kann. Und in diesem Fall haben wir tatsächlich zwei Dinge gleichen Zeit ausgeführt, wo ich gerade bin, wo die Kontrolle der Ereignisschleife zurückgegeben werden kann. Und die Dinge sind so geplant, dass sie asynchron, aber im Wesentlichen gleichzeitig ausgeführt werden. Also, wenn wir hier nur eine zusätzliche Zahl hinzufügen und dass wir ausdrucken können, um zu verstehen, wissen Sie, wo wir in jedem sind. Wir drucken n hier aus, und wir drucken n hier aus, und dann hier wollen wir eine hinzufügen. Dies wird die Aufgabe sein, die wir erstellen und planen. Und dann hier können wir zwei hinzufügen. Also, wenn wir das erledigen, können wir sehen, dass wir zuerst diese Aufgabe neu planen, aber dann warten wir auf diesen Anruf hier , der dann dazu kommt. Und hier hört unsere Hinrichtung auf, weil wir hier nur auf die Antwort warten. Also haben wir die Kontrolle zurück auf die Ereignisschleife gegeben. Und jetzt haben wir eine weitere Aufgabe, die geplant wurde. Und jetzt als eine bequeme Zeit, daran zu arbeiten, weil nichts anderes bearbeitet wird. Und so ist diese Aufgabe jetzt im Grunde, wie wir hier sehen können, und beginnt, ausgeführt zu werden, sobald wir diesen Wartungspunkt hier erreicht haben. Und dann sind wir fertig, oder dann endet unser erstes Coubertin hier. Wir können sehen, dass die Ausführung zu dieser Co-Routine zurückkommt, nachdem wir hier in diesen Schritt gegangen sind. Und dann warten wir hier auf das Ergebnis dieser Aufgabe. Und jetzt führen wir diesen Co-Routine-Block grundsätzlich nicht mehr aus, bis wir hier die Antwort erhalten haben, weshalb wir diesen Aufruf hier haben. Und dann bewerten wir die Antwort darauf, weshalb wir das Hallo hier haben. Wenn wir die Reihenfolge der Ausführung hier umkehren, werden Sie feststellen, dass die Reihenfolge, die wir dort gedruckt haben , auch ändern wird, die hallo zweitletzten haben, und dann haben wir die nach dem Schlafen danach wegen der Reihenfolge der await-Anweisungen hier. So können wir jetzt sehen, dass wir in diese gleichzeitige Natur geraten, denn jetzt haben wir tatsächlich mehrere verschiedene Co-Routinen, die gleichzeitig laufen. In diesem Fall ist es einfach zu. Aber wie Sie wissen, ist eine Co-Routine irgendwie an der Stelle, nur auf ein Ergebnis zu warten , und es gibt die Kontrolle der Ereignisschleife zurück. Es kann tatsächlich weitergehen und Sie können mit der Arbeit an anderen Aufgaben beginnen , bis sie diesen Wartungspunkt erreicht haben. Und dann, sobald eine andere Co-Routine beendet ist, wird die Ausführung oder Kontrolle der Ausführung dieser Co-Routine zurückgegeben. 24. Async Gather: In Ordnung, also haben wir jetzt unser erstes Beispiel gesehen, wie wir diese gleichzeitige Ausführung haben , indem wir Aufgaben planen. Und während eine Co-Routine im Grunde auf eine Antwort wartet, kann die Ausführung einer anderen fortgesetzt werden, was wir hatten, als wir hier eine Aufgabe geplant haben. Und dann passierte die Ausführung einer Art von, wenn es praktisch war, nichts anderes gearbeitet wurde. Aber wir haben immer noch dieses Problem hier, wo zum Beispiel, wir haben diese print hello Aussage. Und dieser wird danach noch erwartet, erst nachdem dieser Schlaf hier beendet ist. Und im Idealfall würden wir nicht wollen, dass diese beiden idealerweise gleichzeitig laufen könnten. Nehmen wir zum Beispiel an, wir hatten hier zwei API-Aufrufe , die überhaupt nicht voneinander abhängen. Also das hier trifft API eins und das hier trifft API auf Wir oder so, auch wenn wir es so hatten , oder wenn wir es so hatten, funktioniert es immer noch nicht so, wie wir es wollten weil wir im Grunde erwarten die Antwort eines API-Aufrufs. Und dann gehen wir dann, dann werden wir nur den Anruf des zweiten einleiten, was nicht das ist, was wir wollen. Wir wollen, dass sie im Grunde sowohl den Start fast sofort, einer nach dem anderen, und dann wollen wir, dass sich diese Timeout-Periode überlappen, so dass all diese Netzwerkwartzeit im Grunde nicht sequentiell geschieht, aber es passiert fast bei zur gleichen Zeit. So oder so, unabhängig davon, wie wir diese Reihenfolge umkehren, werden wir nicht wirklich dazu kommen. Also, wie können wir so etwas machen? Nun, wir können etwas anderes von asynchrone IO verwenden, das heißt sammeln. So können wir in asynchrone IO gehen und hier können wir diese und Sammelmethode verwenden. Und hier können wir nun eine Reihe von Coroutinen setzen und sie werden im Grunde alle gleichzeitig geplant und ausgeführt werden. Wir haben das also nicht nacheinander, aber sie sind alle zeitgleich geplant. Und was auch immer, wissen Sie, was auch immer endet und welche Reihenfolge. Grundsätzlich können wir irgendwie durch das herumspringen. Es gibt immer noch eine Ordnung, die wir hier drin haben, nämlich die Reihenfolge, in die wir sie eintragen. Aber wir sind jetzt in der Lage, all das gleichzeitig und so zu laufen, wie wir es wollten. Also lassen Sie uns das in Aktion sehen. Wie würden wir das tun? Nun, wir können haben, zum Beispiel, sind erste Co-Routine hier, was unsere asynchrone sein wird. Wir werden unsere zweite Co-Routine haben, die Computer Eysencks Schlaf 2 ist. Und dann haben wir unser drittes, das aus Hallo ausdrucken wird. Wir können jetzt die Planung dieser Aufgabe entfernen. Und wenn wir das jetzt ausführen, werden wir bemerken, dass wir in den vor dem Schlafen gehen, der hier ist. Dann gehen wir auch in den „Vor dem Schlafen“, der hier ist. Dann haben wir unseren Druck niedrig, weil beide Co-Routinen sind, sie blockieren nicht, aber sie sind im Wesentlichen, sie warten auf eine Antwort. Und so können sie unsere Ereignisschleife wieder kontrollieren. Also gehen wir hier weiter, wir führen dies aus, wir geben diese Kontrolle der Ereignisschleife. Wir führen durch, wir gehen und hier führen wir durch, wir kommen dazu, bekommen die Kontrolle zurück. Wir gehen rein, hier sind Co-Routine beendet, weil es keine Erwartung gibt. Und dann können wir zurück zur Ereignisschleife und dem Gewicht der Ereignisschleife gehen. Und dann wird es sehen, weil dieser zuerst geplant wurde und sie für die gleiche Zeit schlafen. Wir kommen zuerst hierher. Und so können wir mit der Ausführung fortfahren, bis unsere Co-Routine hier beendet ist. Und dann gibt die Kontrolle, zurück an die Ereignisschleife gegeben und dann sehen wir, was sonst vor sich geht. Also haben wir diesen hier, der dann fertig ist. Also lasst uns dies ein wenig aktualisieren und auch nur für diese Zeit schlafen. Wir werden sehen, dass die Planungsreihenfolge irgendwie das ist, was wir hier haben, aber die Abschlussreihenfolge kann nicht wirklich so sein. Also in diesem Fall werden wir erwarten, dass dieser zuerst geplant wird. Dann werden wir wieder die Kontrolle bekommen. Sobald wir diesen Punkt erreicht haben, können wir anfangen zu rennen. Das hier. Würde das Controlling zurückgeben. Wir haben diesen Punkt erreicht, wir können diesen hier ausführen. Wir haben die gesamte Co-Routine beendet, und jetzt gehen wir zurück zu unserer Event-Schleife. Und an diesem Punkt wird dieser eigentlich zuerst fertig sein weil er langsamer schläft, für weniger Zeit. Damit wir zu diesem hier zurückkommen können. Ich beende diese Co-Routine, weil nach dem Schlaf nichts anderes los ist, nach dieser Print-Anweisung. Und danach haben wir die einzige Co-Routine übrig, die wartete, die hier sein wird. Also, wenn wir dies ausführen, können wir sehen, dass die Reihenfolge, in der sie beenden Punkte, im Grunde können wir dann mit der Ausführung dieser fortfahren. Und damit haben wir jetzt eine viel bessere gleichzeitige Natur, weil wir in der Lage sind, anstatt alle diese Aussagen p sequentiell zu haben, stattdessen haben wir sie alle Arten von gleichzeitig laufen und wir starten sie. Und wann immer wir dies auf 0.1 Co-Routine treffen, können wir im Grunde die Kontrolle zurückgeben und eine andere Co-Routine kann weiterlaufen. Und wenn wir von Control T gegeben haben, wenig t, dann Schleife und alles ist irgendwie läuft. Sobald eine Sache fertig ist, können wir dorthin gehen und wir können mit der Hinrichtung dieses Coubertin fortfahren, um so viel schönere gleichzeitige Natur zu bekommen, die wir eigentlich hinter uns her sind. An diesem Punkt fragen Sie sich vielleicht, na ja, was ist der Unterschied zwischen asynchron und Threading? Also im Allgemeinen, und wenn Sie sich daran erinnern, worüber wir am Anfang gesprochen haben, unser asynchroner hier, läuft dies auf einem Kern und auch jedem einzelnen Thread und alles wird durch diese geplanten Ereignisschleifen gemacht , wo wir eine Möglichkeit haben, Bullen und im Grunde Futures, die repräsentieren, dass eine Antwort kommen wird. Aber es ist noch nicht da. Während mit Threading, erstellen wir tatsächlich mehrere verschiedene Threads und es gibt auch Overhead damit verbunden. Während wir hier nur in einem einzigen Thread sind und wir tatsächlich weniger Overhead haben. Nun, im Allgemeinen, wann würdest du eines dieser beiden verwenden? Nun, Sie würden oder ich würde generell Threading verwenden, wenn wir Arbeiter wie Programme aufbauen, wie wir es in unserem Threading-Modul getan haben, wo wir viele verschiedene Arbeiter hatten, die unterschiedliche Ziele durchführten. Während, wenn Sie nur einzelne Aufgaben haben, wie wir in diesen Fällen mehr haben, dann können Sie zu einem synchron gehen. Offensichtlich, wenn Sie sich viel wohler mit dem einen oder anderen fühlen, werden Sie wahrscheinlich dazu neigen, auf diese Dinge zu gehen, und Sie können wahrscheinlich sehen, erreichen ähnliche Parallelität. Denken Sie daran, dass Sie mit Async nur einen einzigen Kern, einen einzigen Thread machen , während Sie beim Threading mehrere Threads mit einem Kern machen. Es gibt also diesen Unterschied und es gibt auch Overhead mit Threading verbunden. Aber offensichtlich, weißt du, es kommt auch darauf an, ein bisschen zu trösten. Die andere Sache ist, dass Sie in Webanwendungen oft asynchron verwenden werden. Und so ist es sehr üblich, asynchrone und Punktdefinitionen zu haben , wo Sie dann den Endpunkt verbergen können und das wird heißer die Ereignisschleife, so dass Sie wissen, dass Ihre verschiedenen Endpunkte und Ihr Server im Allgemeinen die Ausführung nicht blockieren, da sie versucht, Dinge parallel auszuführen. So asynchron ist es irgendwie zusammenzufassen. Im Allgemeinen, aus meiner Sicht, viel für Aufgaben sowie Web-Entwicklung verwendet. Während Threading, würde ich viel mehr verwenden, um Arbeiter wie Programme zu bauen , wie wir es in unserem größeren Drehmodul getan haben. 25. mit Async Timeouts: Nun, im Allgemeinen, wenn wir es mit Netzwerkkommunikation oder einigen Arten von Io zu tun haben, kann es Probleme an anderer Stelle geben, die eine Art von Unterbrechung verursachen können oder im Grunde einige Dinge viel länger dauern können. Zum Beispiel, wenn ein Server überlastet ist oder momentan nicht reagiert oder sehr langsam, wenn wir versuchen, diesen Server zu pingen, und es dauert für immer, um eine Antwort zu erhalten. Selbst wenn wir eine Art gleichzeitiger Ausführung verwenden, wie wir hier haben, kann es einen Nachzügler geben, der im Grunde alles nimmt und die ganze Sache verlangsamt weil wir darauf warten, dass diese eine Sache beendet ist. Es gibt also eine nette Methode, die wir dafür verwenden können. Haben Sie irgendeine Art von Beschränkungen, wie lange wir auf Antworten warten wollen. Und wir wissen generell, wie schneller die Endpunkte reagieren, sowie die Variabilität, die wir haben. Und wir wissen, dass wir mit sehr hoher Sicherheit in der Lage sind, Antworten zu erhalten und weniger als dieser Zeitraum. Und die Zeitspanne ist ein guter Zeitpunkt hier zu verwenden. Wir können auch etwas, das Timeout genannt wird, verwenden. So können wir zum Beispiel tun, ist, dass wir asynchrone IO Dot warten können. Und das wird im Grunde bedeuten, dass wir auf so viele Sekunden warten werden. Und wenn unsere Co-Routine zu diesem Zeitpunkt nicht endet, dann werden wir eine Ausnahmeausnahme dafür auslösen. Sagen wir mal, wir wollen ihm fünf Sekunden geben. Und wir werden das auch in einen Versuch und außer Aussage einschließen , wo wir speziell ein Timeout Aram fangen werden. Und hier werden wir ausdrucken gestoßen Timeout Fehler. Also in diesem Fall, wenn wir das ausführen, wird alles in Ordnung sein, weil es zwei Sekunden und keine Zeitbegrenzung dauert , es sind fünf Sekunden. Aber wenn wir dies auf, sagen wir dreißig Sekunden, als ob etwas wirklich langsam läuft oder es nur ein Timeout-Fenster von 30 Sekunden gibt und es nicht reagiert. Und wir halten diese Verbindung irgendwie dort und warten auf eine Antwort, aber sie wird nie antworten. Und die Verbindung wird nur nach etwa 30 Sekunden unterbrochen. Wenn wir hier fünf Sekunden warten, dann, nachdem wir diese 5-Sekunden-Marke erreicht haben, werden wir das im Grunde einfach töten. Und wir werden stattdessen einen Fehler erreichen, den wir hier in einer Sekunde sehen können. So können wir sehen, dass ein Timeout-Fehler aufgetreten ist. Und weil wir diese Timeout-Komponente hier haben, jetzt, beachten Sie, dass, weil wir irgendwie auf diesen Ausnahmefall stoßen, wir sehen können, dass wir hier in die Vorschläft gehen. Und wir haben tatsächlich diesen Ausnahmefall betreten. Also die anderen Co-Routinen, die wir auch haben, wie wir hier sehen können, die tatsächlich nicht die Möglichkeit haben zu beenden, weil wir diese Ausnahme mit dem Gewicht für Methode gestoßen haben . Offensichtlich kann dies eine wirklich nette Sache sein, um sicherzustellen, dass die Teile Ihrer Ausführung oder nicht für eine sehr lange Zeit aus äußeren Gründen blockiert werden. Aber natürlich möchten Sie auch vorsichtig damit sein, da es auch andere Dinge unterbrechen kann , die laufen, wenn sie zur gleichen Zeit erwartet werden, wie in diesem Fall, den wir hier haben. 26. Asynchronous für Loops erstellen: Jetzt war ein weiterer Fall, den ich übergehen wollte asynchron for-Schleifen, da er das manchmal sehen kann. Aber ich möchte darüber nachgehen und im Grunde das Verhalten betrachten , um sicherzustellen, dass wir verstehen was genau eine asynchrone FOR-Schleife ist und was sie tut und nicht tut. Also lasst uns voran gehen und unseren asynchronen Schlaf hier ändern , anstatt ein Generator zu sein , der nur Werte ergibt, und dann geht es danach schlafen. Also werden wir sagen, für mich in Reichweite, und wir werden das Ergebnis I liefern. Und dann schlafen wir für i Sekunden. Und sagen wir für I zwischen eins und n. und wir werden sagen, dass n gleich dem Maximalwert zwischen zwei Ende ist. Und nur damit wir etwas tun, oder? Und jetzt, was wir tun können, ist, dass wir eine async for-Schleife verwenden können, und wir werden für k in einem Waschbecken Schlaf 5 sagen, und dann können wir k. ausdrucken Alles klar, also gehen wir voran und führen Sie dies aus und lassen Sie uns auch durch, was passiert. Also hatten wir unsere fünf Jahre als Input, nur weil, naja, das ist irgendwie Überdruck hier draußen noch. Und dann wählen wir sie im Grunde aus und stellen sicher, dass es mindestens zwei sind. Und wir gehen in unsere For-Schleife hier, und wir beginnen von eins bis n. Also wird es von eins bis zu aber nicht mit fünf sein. Also von eins bis vier, wie wir hier sehen. Und dann geben wir diese Antwort zurück, und dann warten wir auf diesen Schlaf, den wir hier haben. Jetzt können wir hier durchgehen, oder die Gesamtausführungszeit beträgt etwa zehn Sekunden. Also, wenn wir eins plus zwei haben, ist drei, plus drei ist sechs, plus vier ist zehn. Also führen wir das immer noch sequentiell aus. Wir machen das nicht gleichzeitig, sonst wird unsere Ausführungszeit vier Sekunden betragen, da also der längste Schlaf, den wir hier haben, oder ungefähr vier Sekunden. Das Wichtigste an diesem Async für ist, dass wir im Grunde eine andere Phase haben , in der wir die Kontrolle der Ereignisschleife zurückgeben können. Anstatt also eine for-Schleife zu haben, in der im Grunde diese Iteration Art von allem passiert, gibt uns der asynchrone Vorwärts eine andere Stufe, in der während dieser Iteration, wenn wir auf eine Antwort warten, wir wieder die Kontrolle der Ereignisschleife geben können und dann kommen Sie zurück zu unserer Coroutine, sobald wir bereit sind, mit unserer Schleife fortzufahren. Das ist also nur eine wichtige Sache zu beachten, dass, wenn Sie einen asynchronen Floor sehen, wenn Sie darüber nachdenken, eine Asynchrone für zu schreiben, es nicht funktioniert. Es läuft nicht gleichzeitig und läuft sequentiell, aber es fügt im Grunde eine weitere Phase hinzu, in der wir der Ereignisschleife die Kontrolle zurückgeben können , so dass andere Dinge mit ihrer Ausführung fortfahren können. 27. mit Asynchronen Bibliotheken verwenden: Das nächste, was ich mir ansehen wollte, ist Verwendung anderer Bibliotheken mit asynchroner Verarbeitung. Einige Bibliotheken unterstützen also asynchron und andere nicht. Und ich möchte nur voran gehen und diese durchschauen und Ihnen im Grunde einen schnellen Vergleich zeigen , wie das aussehen würde. Also werden wir verwenden, und ich habe bereits ein kleines Boilerplate hier im Grunde mit einigen URLs, die ich aufgenommen habe. Was wir tun werden, ist ein sehr einfaches Programm auszuführen, war nur pings jede dieser URLs und dann bekommt nur die Text-Antwort von ihm. Es macht nicht wirklich etwas damit, nur irgendwie es zu bekommen. Also werden wir das auf zwei Arten schreiben. Einer von ihnen wird die synchrone Version verwenden , war gerade dabei, die Anforderungsbibliothek zu verwenden. Also hast du das nicht. Sie können voran gehen und pip-Installationsanfragen wie folgt schreiben. Und dann werden wir auch das IO HTTP verwenden, das HTTP sein wird, wie dieser pip installieren Sie das. Und einer von diesen, Sie können wahrscheinlich vermuten, dass das HTTP uns erlauben wird , es asynchron zu tun, während die andere asynchrone Bibliothek ist. Also fangen wir mit dem synchron an. Wir werden Anfragen importieren. Und was wir tun werden, ist, dass wir nur ein wenig for-loop laufen. Wir werden für URL sagen. In URLs werden wir Anfragen dot get URL aufrufen. Und dann können wir unseren Prozess hier Zeit und wir können sagen unsere, unsere Startzeiten time.Deltatime und unsere Endzeit wird time.Deltatime. Und dann können wir sagen, Kämme nahmen und dann haben wir unsere Endzeit minus Start. Also können wir das einfach ausführen und das wird nur der standardtypische synchrone Weg sein. Und wir können sehen, dass dies ein paar Sekunden dauern wird, wahrscheinlich, sagen 3,5 Sekunden gerade jetzt. Gehen wir also weiter und schreiben Sie die asynchrone Version davon. Und schauen wir uns auch die einzelnen Komponenten und Kahlheit an. Also werden wir tun, stehen vor dem Tod und wir werden sagen, bekommen URL-Antwort. Wir werden hier eine URL übergeben. Und jetzt werden wir unsere AIO-HTTP-Bibliothek verwenden , die wir gerade importiert haben oder die wir gerade installiert haben. Also werden wir das IO HTTP so importieren. Und wir werden mit AIO http Dot Client-Sitzung sagen mit AIO . Als Sitzung werden wir dies zu einer asynchronen Breite machen. Und ich werde in einer Sekunde darüber reden. Und wir werden asynchron mit Sitzung machen, erhalten Sie keine URL als Antwort. Und dann schließlich werden wir eine Gewichtsantwort dot txt zurückgeben. Also gehen wir in der zweiten Zeile über jede dieser Zeilen. Und hier wollen wir natürlich auch sicherstellen, dass wir die Antworten auf die Texte erhalten. So können wir sagen, sync-Text-Antwort wird dies sein. Und hier können wir einfach auf unsere Liste angehängt werden. Und dann können wir etwas Ähnliches tun. Aber hier haben wir unsere Aufgaben. Und für jeden dieser, Sie möchten asynchronisieren o, wir wollten eine neue Aufgabe erstellen, die unsere GET-URL-Antwort aufrufen wird. Wir werden passieren. Das ist nicht das, was ich will. Bewegen Sie sich überhaupt. Wo sind wir? - Hier? Wir rufen sie an, kommen durch unsere Antwort. Wir werden unsere URL als Eingabe hier zur Verfügung stellen. Und dann werden wir auf Async IO Dot sammeln warten. Und wir werden in alle unsere Aufgaben klicken und im Grunde diese ganze Liste entpacken, um sie als einzelne Argumente zu liefern. Und dann wird unsere asynchrone Text-Antwort die Ausgabe sein, die wir daraus erhalten. Und dann können wir hier sagen, dass asynchrone Anfragen dies genommen haben. Jetzt gehen wir einfach voran und führen das aus. Und dann gehen wir weiter und kommen zurück zu dieser Methode hier. Wir sind zurück zu dieser Co-Routine, eher um zu verstehen, was genau vor sich geht. Also lassen Sie uns das einfach ausführen, damit wir die Leistung tatsächlich vergleichen können. Also haben wir unseren synchronen Prozess im Gange. Oh, ich habe vergessen, unser Objekt hier zu initialisieren. Also lasst uns weitermachen und das noch einmal ausführen. Da gehen wir. Mit unserem synchronen Prozess dauerten wir etwas mehr als drei Sekunden, und mit unserem asynchronen Prozess dauerten wir etwa 1 Sekunde. Also lassen Sie uns voran und werfen einen Blick auf das hier. Also, was los ist, da wir mehrere verschiedene Pacing mit haben, also wenn Sie in Python für ein wenig programmiert haben, sind Sie wahrscheinlich vertraut mit der, with - Anweisung, die im Grunde ist, dass wir etwas als Kontext oder Argumentation erstellen oder Context Manager, im Grunde die Erstellung sowie das Abreißen von allem, was wir haben, behandelt und wir müssen uns keine Sorgen darüber machen, etwas zu schließen. Wir waren in der Lage, es in diesem Zusammenhang mit dieser Aussage hier zu verwenden. Jetzt die asynchrone mit, dass wir hier zweimal sehen. Jedes dieser Zeiten geben wir im Grunde die Möglichkeit für die Ereignisschleife. Zweitens geben wir im Grunde die Kontrolle über die Ereignisschleife zurück und wir geben die Möglichkeit, mit anderen Aufgaben zu beginnen oder fortzufahren. Im Grunde haben wir hier drei Instanzen, eine mit dem Gewicht und die anderen zwei mit unseren asynchronen Kontext-Managern hier, wo wir die Kontrolle zurück auf die Ereignisschleife geben, so dass sie möglicherweise mit etwas anderem weitermachen kann. Es gibt also eine Menge Kontrolle an die Ereignisschleife, die hier vor sich geht. Das macht es wirklich schön und wie asynchron, und vor allem mit diesen verschiedenen Teilen. Einer von ihnen würde also tatsächlich eine Sitzung aus unserem Session-Pool bekommen. Dann würde der nächste tatsächlich die Anforderungen ausführen, was einen Großteil des Netzwerkwartens beinhalten würde. Und dann würde die andere Komponente tatsächlich die vollständige HTML-Antwort herausbekommen, weil wir das möglicherweise nicht immer haben. Und so müssen wir all diese Daten sammeln und im Grunde in eine Variable parsen. Und hier ist auch eine Wartezeit involviert. Also für jede dieser Komponenten, wo wir tatsächlich Art wartende Komponente haben können. Wir geben grundsätzlich die Kontrolle über die Ereignisschleife zurück , bis wir bereit sind, damit fortzufahren. Es gibt also eine Menge asynchron oder es gibt viel Kontrolle über die Ereignisschleife zurück. Diese verschiedenen Anrufe, die wir hier machen, im Grunde tun wir es dreimal. Während für unsere Anfragen offensichtlich die Anfragen-Bibliothek selbst. Wo sind wir? Los geht's. Das selbst ist also nur ein blockierender Anruf. Und es gibt keine, es gibt kein asynchrones Abrufen einer Sitzung aus einem Pool. Wir verwenden derzeit auch keine Sitzungen in diesem Fall. Wir bekommen die Anfrage nicht asynchron, wissen Sie , wie wir es in diesem Fall tun würden. Und wir sind auch nicht asynchron Art, diese HTML-Daten zu bekommen und sie im Hintergrund zu sammeln und dann weiter zu machen, und wir sind bereit dafür. Jetzt können wir dies natürlich ein wenig optimieren und wir können dieses Selbst wie ein asynchrones def einfügen, URLs mit Anfragen erhalten, und wir werden die URL hier einfügen. Und dann können wir hier tun, wir können das einfach zurückgeben. Aber wie Sie wahrscheinlich auch in einer Sekunde bemerken werden, wenn wir unsere Aufgaben hier haben und wir planen diese Aufgaben. Also gehen wir in eine Spüle, io dot erstellen Aufgaben und wir werden aus Stiften testen. Und wenn wir dies als Aufgabe erstellen möchten, indem wir den URL-Parameter übergeben, gibt es immer noch keinen Warten-Aufruf irgendwo. Selbst wenn wir versuchen, diese asynchrone Methode von async zu verwenden, weiß ich, Don sammeln, und wir versuchen nur, alle diese Aufgaben asynchron auszuführen. Und irgendwo hier sollten wir unsere Sink-Text-Antwort haben, ich denke, es wurde genannt. Selbst wenn wir versucht haben, diesen Ansatz zu verwenden, werden wir keinen Leistungsvorteil daraus ziehen weil es nirgendwo einen Warteanruf gibt. Es gibt keinen Punkt, an dem wir die Kontrolle zurück in die Ereignisschleife zurückgeben. Also, selbst wenn wir versuchen, dies in wie eine asynchrone Funktion zu wickeln, wie wir hier sehen können. All dies ist ein synchroner Prozess und es blockiert vollständig. Während in unserem asynchronen Prozess haben wir im Grunde diese verschiedenen Möglichkeiten und bekommen die Sitzung aus dem Pool, die tatsächliche Ausführung der Anfrage sowie das Parsen der Text-Antwort, um einen Text zu erhalten Antwort aus. Jede dieser drei Komponenten ermöglicht es uns im Grunde, die Kontrolle der Ereignisschleife zurückzugeben , so dass andere Dinge gleichzeitig passieren können oder während dieses Ding stattdessen wartet. Während wir in unserem synchronen Fall keine Möglichkeit haben, dies zu tun und wir sind grundsätzlich blockiert, bis diese Anfrage sie absendet, die Antwort erhält, die Text-Antwort analysiert. All das ist also ein blockierender Prozess. Wie wir sehen können, gibt es einige große Vorteile, die wir tatsächlich erhalten können asynchrone Anfragen verwenden. Aber wir müssen vorsichtig sein, dass wir auch die entsprechende asynchrone Bibliothek verwenden. In diesem Fall wird es ein 0 HTTP für die Dateieingabe und -ausgabe sein. Es gibt auch tatsächlich etwas namens AI-Datei, die Sie verwenden können, wo Sie Dateien lesen und schreiben können, sowie nur allgemeine Dateioperationen asynchron wie diese. Es gibt auch andere Dinge wie Datenbankverbindungen. Es gibt viele asynchrone Bibliotheken, die Sie dafür wiederverwenden können. Sie müssen jedoch sicherstellen, dass Sie, wenn Sie versuchen, dies asynchron zu machen, die entsprechenden Bibliotheken auch verwenden müssen, die diese asynchrone Weise unterstützen. Andernfalls werden Sie nur blockierende Komponenten haben, da es sich um einen synchronen Prozess handelt und keine Kontrolle an die Ereignisschleife zurückgegeben wird. 28. Die Async Wait: Alles klar, wir haben jetzt ein paar ziemlich coole Sachen mit asynchronen Prozessen gesehen. Aber lassen Sie uns voran und schauen Sie uns eine weitere coole Sache an, die warten wird, bis einige Koordinaten abgeschlossen sind oder einige Aufgaben abgeschlossen sind und sich dann mit diesen beschäftigen und irgendwie iterativ umgehen. Denn momentan haben wir mit sammeln gesehen , dass wir im Grunde auf alles warten, um zu vervollständigen. bedeutet, wenn wir ein paar Dinge haben, die nur eine kurze Zeit in Anspruch nehmen , und eines davon ist das ein Nachzügler. Dies kann natürlich auch unser Programm verlangsamen. Also werde ich wieder asynchrone IO importieren. Ich werde meinen, wenn der Name gleich Haupt ist. Und hier werde ich nur asynchronen IO-Punkt ausführen, unsere Haupt-Co-Routine ausführen, und lass uns voran gehen und das finden. Ich werde schreiben. Und ich werde auch nur noch mal den Schlaf benutzen. Also gehen wir in asynchrone def und wir werden dies wieder unseren asynchronen Schlaf nennen. Und hier werden wir einen Umfang haben. Ich, wie lange wir schlafen werden. Oder wenn wir wollen, können wir es ein wenig expliziter über sie betrachten und es so etwas wie eine Dauer nennen. Und dann werden wir sagen, wir warten auf den Async-IO-Punkt-Schlaf für die Dauer. Und dann werden wir nur die Dauer zurückgeben. Gerade genommen, haben auch etwas von dort zurückgekehrt. Alles klar, in unserer Coroutine hier möchte ich im Grunde 10 Aufgaben planen. Und dann, wenn einer von ihnen abgeschlossen ist, möchte ich in der Lage sein, mit ihnen umzugehen. Was ich also tun werde, ist, dass ich hier eine Variable namens „Pending“ haben werde. Und Sie werden sehen, warum in einer Sekunde, die ich initialisieren werde, um nur ein leerer Satz zu sein. Dann werde ich für mich im Bereich 1 bis 11 iterieren. Und für jeden von ihnen werde ich ein Element hinzufügen. Und wir werden sagen, asynchrone IO Punkt erstellen Aufgabe. Wir werden also unseren asynchronen Schlaf mit der spezifischen Dauer erstellen. Also im Moment und wir haben die Erstellungsaufgabe schon gesehen. Wir erstellen nur eine Reihe von Aufgaben, die wir in diesem Set hinzufügen , die wir als ausstehend bezeichnet haben. Ok? So können wir jetzt etwas namens Async, IO dot wait verwenden. Und hier können wir ein Intervall von Aufgaben zur Verfügung stellen. So zum Beispiel ein Satz oder eine Liste von Aufgaben. Und, und dafür können wir unterschiedliche Verhaltensweisen haben, was wir in einer Sekunde betrachten werden. Also lassen Sie uns es einfach irgendwie mit dem Standardverhalten für den Moment behalten. Also werden wir unser erstes einziges Intervall von Aufgaben haben, das nur das ausstehende sein wird, das wir hier haben. Und die Rückkehr, die wir tatsächlich davon bekommen. Die Variablen werden als „done“ und „pending“ aufgerufen. Deshalb haben wir diesen Variablennamen hier. Weil die Antworten, die wir bekommen, tatsächlich in zwei Dinge aufgeteilt sind. Dies sind also die Aufgaben, die abgeschlossen wurden, und die gelben, die Aufgaben, die noch ausstehen. Also lassen wir das jetzt so. Und dann werden wir nur ausdrucken sind erledigte Aufgaben. Und wir drucken auch unsere ausstehenden Aufgaben aus. Und lassen Sie das so, wie es für jetzt ist, und wir werden in einer Sekunde einige weitere Änderungen daran vornehmen. Lasst uns einfach voran gehen und das zuerst ausführen. Und ja, geh einfach weiter und drücke Enter. So sollte etwa 10 Sekunden dauern. Ich habe nicht wirklich irgendwelche zusätzlichen Druck hier, leider gerade jetzt außer für sind fertig und am Ende hier anhängig. Aber da gehen wir. Also haben wir unsere erste Ergebnismenge, die dieses hier sein wird. Und wir können sehen, dass wir eine Reihe haben, welche Art von hat die Aufgabe, sowie das Ergebnis, das tatsächlich mit ihm kam. Und dann haben wir endlich auch dieses leere Set hier, was im Grunde die verbleibenden ausstehenden Aufgaben ist. Wir haben also etwas Cooles, aber im Wesentlichen, was wir jetzt haben, ist irgendwie dasselbe, was wir bereits mit der Versammlung im Wesentlichen haben, weil wir immer noch darauf warten, dass alles fertig ist. Es gibt also verschiedene Möglichkeiten, wie wir dies tun können. Eines der Dinge, die wir tun können, ist, dass wir etwas wie ein Timeout hinzufügen können. Jetzt ist dieses Mal anders als das, was wir für das Gewicht hatten, in diesem Fall überprüfen wir im Grunde oder wir werden im Grunde unser Ergebnis hier für Don und Pending bekommen , sobald wir dieses Timeout-Limit erreichen. Aber das bedeutet nicht, dass unsere aktuellen geplanten Aufgaben abgebrochen werden. Es bedeutet nur, dass wir zu dieser Zeit unsere Antwort bekommen werden. Was wir also tun können, ist, dass wir sagen können, während es noch ausstehende Aufgaben gibt. Also, während die Länge unseres ausstehenden Satzes größer als 0 ist, gehen wir voran und drucken das aus. Also, wenn wir das jetzt ausführen, sollten wir sehen, wie es etwa alle zwei Sekunden gedruckt wird, was wir hier haben. Offensichtlich gibt es eine Menge Spam an unserer Ausgabe, wie wir sehen können, weil es sehr ausführlich ist. Jedes dieser Elemente, es gibt eine Menge Details, aber wir können sehen, dass die Menge, die wir für das Anhängen von Ergebnissen haben , im Grunde irgendwie nur kontinuierlich in der Größe abnimmt. Und so kommen wir alle zwei Sekunden wieder und wir sehen, welche Ergebnisse bereits beendet sind. Also, was drin ist, sind getan. Und dann fahren wir einfach mit den aktuellen ausstehenden Aufgaben fort. Nun, natürlich, wenn Sie Ergebnisse rausbekommen wollen, wollen wir das wahrscheinlich auch tun. Und so können wir tatsächlich durchlaufen sind Aufgaben erledigt. Und wir können für erledigte Aufgaben sagen, Portal sagen für Don Aufgabe und erledigt, wenn Sie das Ergebnis erhalten möchten, können wir einfach warten, erwarten, dass Element oder wir können diese Aufgabe erwarten. Und von dort können wir das Ergebnis, das wir hier haben, herausbekommen. Also lasst uns weitermachen und das noch einmal ausführen. Wir werden also im Grunde die Reihenfolge sehen in der wir erwarten würden, dass diese Aufgaben beendet werden. So können wir hier sehen, dass wir alle zwei Sekunden, im Wesentlichen, das stoppen oder wir erreichen eine Auszeit für unser Coubertin hier und wir bekommen die Antworten. Aber diese Aufgaben sind noch geplant und sie sind technisch nicht und Fortschritt, wie wir sehen können, denn es sind alle zwei Sekunden, die wir irgendwie die Antworten bekommen. Und wir können dann über sie schleifen. Und wenn wir dies verwenden warten, können wir das tatsächliche Ergebnis wie folgt erhalten. Aber offensichtlich ist das, das ist ziemlich nett weil wir jetzt nicht warten müssen, bis alles fertig ist, aber wir können Art von Prozessen in Blöcken, wie es beendet ist. Und natürlich, etwas, das wir auch tun können, ist, dass wir in diesem Fall mehr Dinge zur ausstehenden Liste oder zum ausstehenden Satz hinzufügen können . Was wir zum Beispiel tun könnten, ist, dass wir, wissen Sie, unten hier nur, wir haben mehr Aufgaben hinzuzufügen. Ich werde nur eine sehr einfache, nur eine Aufgabe hinzufügen, die einmal schläft. Und wir werden im Grunde sagen, wir werden das einmal tun. Aufgabe hinzufügen entspricht false. Und dann werden wir sagen, wenn diese Aufgabe wahr war, wenn Aufgabe hinzufügen, dann wollen wir die Aufgabe hinzufügen und wir werden diese Variable einfach auf false setzen. Das ist also einfach unendlich und bleibt im Grunde in dieser Schleife stecken. Aber der Punkt, den ich versuche, damit zu machen, ist, dass wir einfach weiter hinzufügen können , um in diesem Fall noch weitere Aufgaben sind ausstehend gesetzt. Und das gibt uns viel mehr Flexibilität, denn wenn die Dinge eintreten, können wir diese Aufgaben auch weiterhin erstellen und planen. Und wir können diese Antworten irgendwie erhalten, wann immer sie bereit sind , dieses asynchrone IO-Punktgewicht zu verwenden. In diesem Fall verwenden wir ein bestimmtes Timeout, aber es gibt tatsächlich auch eine andere Methode für uns. Und dieser Parameter wird zurückgegeben, wenn. Und hier können wir verschiedene Optionen haben. Der Standard, denke ich, ist alles abgeschlossen und in allen Großbuchstaben geschrieben. Wenn wir also kein Timeout festlegen, dann werden wir nur unsere Antwort erhalten, wenn alle Aufgaben abgeschlossen sind. Und das haben wir am Anfang gesehen, als wir diesen Parameter nicht zur Verfügung gestellt haben, dass wir im Grunde darauf warten, dass alles abgeschlossen ist. Also werden wir einen bis 10 ausgedruckt sehen. Und wenn wir es hinzufügen, werden wir hier ganz am Ende noch einen sehen. Und wir können sehen, dass wir im Grunde darauf warten, dass alles fertig ist. Dies ist kein Auftrag, da Sets nicht bestellt sind. Also bekommen wir nur irgendwie alle abgeschlossenen Aufgaben, wie wir hier haben. Aber wir können das auch ändern, aber wir sind es nicht, wenn wir nicht wirklich ein Timeout verwenden wollen, weil vielleicht Ihre Aufgaben tatsächlich extrem schnell enden werden und wir nicht wirklich sicher sind, was wir dort verwenden sollen, oder wir Irgendwie wollen wir es tun, wenn Aufgaben fertig sind. Wir können auch die return one Anweisung verwenden, um zuerst abgeschlossen zu werden. Das bedeutet also, wenn etwas abgeschlossen ist, dann verlassen wir uns hier im Grunde irgendwie aus dieser Co-Routine und können mit dem Rest weitermachen. In diesem Fall werden wir sehen, dass diese Zahlen nacheinander gedruckt werden. Wie wir hier sehen können. Das liegt daran, dass jede Sekunde eines unserer Coroutinen eine unserer Aufgaben ist, es ist tatsächlich abgeschlossen. So können wir sehen, dass dies eigentlich auch wirklich, wirklich coole Sache zu tun ist. Denn im Vergleich zu all den anderen Dingen, wissen Sie, wir können dort auf Probleme stoßen, wo im Grunde, weißt du , wenn eine Sache viel, viel länger dauert als alles andere, dann werden wir immer noch viel Zeit verbringen Warten. Und so diese Gewichte Co-Routine, die wir zur Verfügung haben, erlaubt uns tatsächlich viel mehr Flexibilität in diesem Sinne, um wirklich zwei Dinge zu bekommen, entweder wenn sie bereit sind oder auch innerhalb eines bestimmten Zeitintervalls, so dass wir fortfahren können Verarbeitung von Dingen, die getan werden. Und wir können auch weitere Aufgaben hinzufügen, so dass sie auch angefangen wirklich ein viel dynamischeres und noch mehr gleichzeitiges Programm zu erhalten. 29. Kombinieren von Async und Multiprocessing: Also, jetzt möchte ich einen Blick darauf werfen, wie wir Multiprocessing und asynchrone Programmierung kombinieren können . Weil wir zuvor darüber gesprochen haben, können wir nur eine Ereignisschleife pro Thread haben. Aber etwas, an das wir uns in Python erinnern müssen, ist, dass wir auch dieses Ding haben, das eine globale Interpretersperre genannt wird, was im Grunde die tatsächliche Parallelität einschränkt, die wir bekommen können. Aber zum Glück, wenn wir Multiprocessing machen, haben wir tatsächlich eine Gill pro Prozess. So können wir eine Menge Nutzen aus der vollständigen Hardware, die uns zur Verfügung steht, sowie einige der Einschränkungen der Parallelität von Python durch die Verwendung vonMultiprocessing und Kombination mit asynchron machen sowie einige der Einschränkungen der Parallelität von Python durch die Verwendung von . Also werden wir voran gehen und asynchrone IO importieren. Und wir werden auch weitermachen und Multiprocessing importieren. Und wir werden haben sind, wenn Name gleich Hauptanruf ist. Aber im Moment werden wir das einfach weitergeben. Und im Moment werde ich eine Klasse definieren, die Multi Processing Async genannt wird. Und das wird von Multiprocessing erben, nicht verarbeiten. Und was diese Klasse tun wird, ist, dass sie einen Prozess für uns auslösen wird. Und in diesem Prozess starten wir dann unsere asynchrone Ereignisschleife. Also werden wir voran gehen und die Initialisierung aufrufen und einfach die Elternklasse initialisieren. Und wir werden auch als Parameter einige Dauern zur Verfügung stellen , denn was wir tun werden, ist, dass wir nur eineArt langwierigen Netzwerk-E/O-Timer oder einfach eine andere E/A-Zeit emulieren, um Art langwierigen Netzwerk-E/O-Timer oder einfach eine andere E/A-Zeit emulieren einfach die Schlaf-Co-Routine wieder zu verwenden. Also werden wir unsere asynchrone definieren lassen. Und wir nennen dies einfach den asynchronen Schlaf. Und hier können wir in der Dauer passieren. Und alles, was wir tun werden, ist, dass wir unseren asynchronen IO-Punkt-Schlaf für diese Dauer erwarten . Und das können wir tatsächlich eine statische Methode erstellen , da wir hier keines unserer Klassenattribute verwenden. Dann brauchen wir auch unsere Run-Methode. Also, das werden wir nur den normalen Weg definieren. Und in unserer Run-Methode, sie sind hier wollen wir anfangen, tatsächlich unsere Ereignisschleife zu konsumieren. Also gehen wir in den asynchronen IO-Punktlauf voran. Und jetzt müssen wir den Haupteinstiegspunkt für unsere Ereignisschleife bereitstellen, was wir tun wollten. Also mussten wir diese Co-Routine auch innerhalb unserer Klasse finden. Also werden wir in asynchrone def gehen. Und dann werden wir einfach, Hey, ich habe hier, wir nennen das aufeinanderfolgende Schlafplätze. Und was wir hier tun werden, ist, dass wir eine Liste von Aufgaben haben, die wir zuerst planen, und dann werden wir einfach auf sie warten. Also werden wir weitermachen und nun, wir können unsere ausstehenden haben, was wieder unser Set sein wird. Und dann werden wir für die Dauer sagen, in der Dauer unserer anstehenden. Wir werden hinzufügen und dann werden wir eine Aufgabe erstellen. So erstellen wir eine Aufgabe mit dem self.age async, schlafen für diese Dauer. Also im Grunde, was wir auch in der letzten Lektion getan haben, haben wir unser ausstehendes Set. Dann planen wir eine Reihe von Aufgaben basierend auf der Eingabedauer hier. Und wir werden das alles im Auge behalten, da ausstehende Set. Und dann werden wir sagen, während die Länge der Patentierung größer als 0 ist. Und dann sagen wir fertig und beleidigt gleich asynchrone IO-Punktgewicht. Und wir werden auf unsere geplanten Aufgaben warten. Und lassen Sie uns eine Zeitüberschreitung von nur 1 Sekunde hier verwenden. Und wir sagen vier, erledigte Aufgabe und erledigt. Wir werden die Antwort, die wir haben, und die Aufgabe, die momentan nichts ist, ausdrucken . Also lasst uns einfach hier voran gehen und einfach die Dauer zurückgeben , nur damit wir etwas zurückgeben. Alles klar, und dann werden wir das in unserer Eingabemethode für die Multiprocessing-Klasse aufrufen . Also hier werden wir unseren Code ausführen, Selbstpunkt-aufeinanderfolgende Slips. Okay, also lasst uns das noch einmal durchgehen , in Bezug auf das, was wir hier eigentlich tun. Wir erben von der Multiprocessing-Punkt-Prozessklasse. Und das bedeutet, dass wir, wenn wir diese Klasse initiieren, im Wesentlichen ein Kind initiieren, das von diesem Prozess erbt. So können wir einen neuen Prozess dafür erstellen, der auf einem separaten Kern uns separate CPU laufen kann. Wir werden es auch mit einer Reihe von Dauern zur Verfügung stellen. Auch hier ist dies nur um etwas zu haben , so dass eine Aufgabe verbindet, für uns ausgeführt werden. Jetzt unser Einstiegspunkt, und Sie werden sich daran erinnern, aus dem Threading. Wir sind dafür nicht zu viel ins Detail gegangen, für Multiprocessing, aber Sie werden sich daran erinnern, wenn Sie Threading. Es ist, wann immer wir die Punkte starten aufrufen, Das ist, wo wir diese Run-Methode hier ausführen werden. Und in unserer Ausführungsmethode stellen wir nur den Einstiegspunkt für unseren asynchronen Prozess bereit. Also werden wir asynchrone IO Dot Run nennen. Und hier werden wir nur die Haupt-Co-Routine haben, die dieser aufeinanderfolgende Schlaf sein wird, die wir hier definiert haben. Und jetzt werden Sie dies wahrscheinlich aus der vorherigen Lektion erkennen, wo wir nur hinzufügen, um eine Reihe von Aufgaben zu planen. Und jede dieser Aufgaben muss nur für eine bestimmte Dauer schlafen. Und während wir noch ausstehende Aufgaben haben, werden wir nur diese asynchrone IO-Methode „Don't Wait“ verwenden. Mit unseren ausstehenden Aufgaben hier mit einem Timeout von 1 Sekunde und jede Sekunde, die wir durchlaufen werden, sind erledigte Aufgaben und wir werden die Ergebnisse mit diesem Warteruf hier ausdrucken. Jetzt ist das coole Ding dabei, dass wir mehrere Prozesse erstellen können. Und sie können dann, wir können dann die Arbeit so aufteilen. Und wir können tatsächlich mehrere Ereignisschleifen laufen lassen. Einer wird bei jedem Prozess sein. Lassen Sie uns also die Anfangsdauer erstellen, die wir einfach initialisiert werden können, um leer zu sein. Und dann sagen wir für mich im Bereich von 1 bis 11, genau wie wir es für zwei Dauer getan haben, wir werden I anhängen und jetzt können wir auch zwei Prozesse erstellen, wenn wir wollen. Also lasst uns einfach unsere Liste der Prozesse haben. Und wir werden für mich in Bereich 2 sagen, und ich werde hier nicht allzu viel tun. Ich werde an unseren Prozess und initialisierte Version unseres Multiprocessing Ass und Klasse hier oben anhängen . Und wir werden es mit einigen Dauern initialisieren. Und das werden Dauern sein. Und dann gehen wir von i nach oben, also musst du ich mal 5 machen, bis ich plus ein mal fünf. Und so weiter. Auf diese Weise gehen wir im Grunde nur in Schritten von fünf. Also, wenn ich 0 bin, gehen wir von 0 auf fünf. Es werden also die ersten fünf Elemente sein. Und wenn ich einer bin und wir von fünf bis zehn gehen. Also im Grunde Tech nehmen die zweiten fünf Elemente von dort. Und jetzt haben wir unsere beiden Prozesse, aber wir müssen sie immer noch starten. Also werden wir für P und Prozesse sagen, wir werden einfach p dot start am Ende für p und Prozesse nennen, wir werden P dot join nennen. Also warten wir darauf, dass die fertig sind. Na gut, also gehen wir weiter und lassen das hier laufen. Und es sieht so aus, als hätte ich hier oben einen Syntaxfehler. Also lass mich weitermachen und einen Blick darauf werfen, was hier vor sich geht. Und gehen wir weiter und blättern Sie durch unsere Protokolle. Also war unser Coubertin nie gewichtet. Also lasst uns das noch einmal versuchen. Da gehen wir. Also jetzt laufen wir im Grunde auf zwei separaten Prozessen. Und ja, wir sind in der Lage, das irgendwie schön zu machen. Einer von ihnen ist die Planung einer Reihe von Aufgaben hier sie eine Planung der anderen Reihe von Aufgaben wollen. Offensichtlich ist das nicht super optimal, denn zum einen schlafen wir nur für zehn Sekunden und wir haben eine Menge von der kürzeren Aufgabe auf einem Prozess und viele der längeren Tests setzen einen anderen. Ein Prozess wird also tatsächlich enden. So können wir auch hier ausdrucken. Prozess, der auf Prozessen abgeschlossen ist, wird vor dem anderen enden, was bedeutet, dass es einige Zeit gibt, wo einer unserer beiden CPUs in diesem Fall, die wir verwenden, oder wenn zwei Kerne, die wir verwenden Leerlauf sitzen, während der andere läuft immer noch. Also natürlich können wir diese Arbeitslast besser verteilen , um hoffentlich eine bessere Wirkung daraus zu erzielen. Aber es ist immer noch, es funktioniert gut. Jetzt sind wir in der Lage, sowohl eine Multiprocessing als auch async miteinander zu kombinieren und konnten einige der Einschränkungen umgehen, die wir mit einem einzigen Thread haben würden und nur eine einzelne Ereignisschleife ausführen können. Und im Grunde machen die meisten Nutzung aus einer Hardware, wenn wir mehr als einen Kern haben, indem wir Multiprocessing nutzen können. Und dadurch kann man an jedem einzelnen Prozess eine individuelle Ereignisschleife laufen lassen, die uns hoffentlich auch helfen kann, die Dinge noch schneller zu beschleunigen. Weil wir in diese Grenzen geraten können, wo wir tatsächlich noch viel Zeit mit dem Warten verbringen werden, nur weil, weißt du, aus welchen Gründen auch immer es sein mag, dass die Dinge nur langsam sind und wir immer noch können, auch wenn Wir haben Co-Routinen, wenn wir Tausende von Co-Routinen haben, die plötzlich mit Aufgaben geplant sind, können wir immer noch nur zwischen einem von ihnen auf einmal abschalten. Wenn wir also mehr als eine Ereignisschleife haben, sind wir über mehr als einen Prozess, wir können tatsächlich schneller durch mehr Arbeit kommen. Und wenn erledigte Aufgaben erledigt sind, können wir sie schneller bekommen oder wenn sie fertig sind, Sie warten Prozess. Wir können schneller auf sie zurückkommen, damit sie ihre Arbeit schneller fortsetzen oder Dinge nachgelagert weiterleiten und wirklich kompliziert werden können . Auch wie in unserem Threading-Beispiel. Aber ich nehme es wirklich auf die nächste Ebene, denn jetzt kombinieren wir dieses asynchrone Verhalten, in dem wir diese Parallelität erhalten können, sowie die Multiprocessing, die uns zusätzliche Parallelität mit zusätzlicher Rechenleistung gibt. Und so sind wir in der Lage, sowohl mit den Netzwerk-Timeouts mit dem asynchronen Prozess als auch mit allgemeinen IO umzugehen , nicht einmal Timeout, um nur allgemeine IO-Wartezeiten zu sein. Und wir können unsere Hardware optimal nutzen, indem wir das Multiprocessing nutzen, so dass wir alle uns zur Verfügung stehenden Ressourcen nutzen und das bestmöglich nutzen können. Jetzt noch eine letzte Sache, die ich erwähnen möchte, das ist etwas, das wir hier nicht getroffen haben und vielleicht nicht einmal etwas, mit dem Sie jemals zu tun haben, aber nur bewusst, dass Aufgaben können auch Timeout. Also, wenn Sie zu viele Dinge planen und Sie einen Timeout-Parameter haben. Es könnte sein, dass Ihre Aufgaben tatsächlich Timeout, bevor Sie sogar zu ihnen kommen können. Seien Sie also vorsichtig, wenn Sie auf ein paar extrem seltsame Probleme stoßen weil Sie dieses extrem komplexe Programm gebaut haben, das nur eine Menge Arbeit macht, dann könnte das etwas sein, auf das Sie achten möchten, ist, wissen Sie, Ich meine Zeitplanung zu viele Aufgaben zur gleichen Zeit und oder einige von ihnen tatsächlich Timeout, bevor ich überhaupt mit ihnen fertig werden kann. In diesem Fall möchten Sie möglicherweise Ihre Chargengrößen reduzieren , damit Sie diese besser durchstehen können. Also nur ein letzter Tipp sind sie, wenn Sie wirklich tief damit gehen und versuchen, etwas sehr Großes und Komplexes zu bauen , das sich um viele Dinge kümmern wird. Achten Sie nur auf Ihre Chargengrößen. Weil, weißt du, das könnte etwas nicht einmal sein, aber es könnte etwas sein, auf das du stoßen könntest. Und ich kann eine Menge Kopfschmerzen verursachen, wenn du nicht einmal sicher bist, wonach du suchst. Aber ja, ich hoffe, dass dir das gefallen hat und ich hoffe, du hast viel gelernt und ich hoffe, du kannst jetzt ein paar wirklich coole Parallel- und Parallelprogramme erstellen.