Transkript: Das Python Importsystem
Vollständiges Transkript der Episode. Zeitstempel beziehen sich auf die Audiowiedergabe.
Ja, hallo liebe Hörer und Hörer, willkommen beim Python Podcast in der Episode Nummer 33.
Die hatten wir letztes Mal aus Versehen ausgelassen.
Deswegen müssen wir die Episodenummer jetzt ergänzen.
Ja, was machen wir heute?
Wir wollen heute über Imports reden.
Hi Jochen.
Ja, Liallo, willkommen Dominik.
Hi Johannes.
Ja, hallo, ich bin auch mal wieder da.
Ja, wir kennen es ja alle schon.
Ja, also über das Python-Import-System heute sprechen, vielleicht ein paar kleine News vorweg, wie wir das gerne tun und dann gehen wir so ein bisschen in die Details.
Habt ihr
News mitgebracht?
Ja, also die einzige News, die ich habe, ist, dass Apple sich gerade den größten Pair-Unfug aller Zeiten einholt.
Aber da ich kein Apple-Gerät habe, geht es nur ein kleines bisschen mehr.
Okay, das Problem habe ich auch nicht.
Jochan, erzähl du doch mal, wie viel ich das für dich hatte.
Ja, nee, tatsächlich ist es pair-technisch, würde ich sagen, auch aus meiner Perspektive ein großer Unfall.
Wenn man sich jetzt anguckt, was sie technisch tun, ist es nicht so furchtbar.
Was ist denn überhaupt passiert?
Vielleicht erstmal so die Story.
Sie haben irgendwie war das eine Pressmeldung oder Sie scannen jetzt irgendwie.
Das war eine Pressemeldung und es war eine technische Meldung, glaube ich.
Dass sie jetzt Cesam angemacht haben, Content Scanning.
Keine Ahnung, was es bedeutet.
Jedenfalls will Apple jetzt in die Fotos reingucken und verbotene Inhalte finden.
Ja, das ist natürlich so ein bisschen das.
Mit modernster Technologie.
Ja, es ist zum Glück ist es nicht das Schlimme-Technologie, was man halt auch nehmen könnte, aber sondern es ist halt irgendwas total Billiges, einfach nur Hashes und Bilder angucken.
Also im Grunde nur gucken, ist das ein Bild, das auf irgendeiner Liste draufsteht von verbotenen Bildern.
Ja, aber haben die nicht auch gesagt, dass sie so neuronale Netze drüber laufen lassen und dann Sachen erkennen wollen?
Er ist der nächste Schritt.
Ja, ja, genau.
Das ist halt der PPA-Gau-Teil.
Ja, genau, und das ist auch so ein bisschen der Präzedenzfeier.
Früher war Apple ja immer so, ja, es ist auf deinem Gerät und es ist alles sicher und wir können da gar nicht.
Und jetzt ist es so, ja, wir gucken doch mal rein.
Ja, das also entweder war es ein Unfall, sozusagen, dass jemand nicht darüber nachgedacht hat, dass wenn man das so sagt, dass das dann genau das auslöst bei den Leuten.
Oder ist es halt irgendwie, aber das kann ich mir auch nicht vorstellen, weil das wäre ja so ein abrupter Strategiewechsel, das wäre auch schon irgendwie komisch.
Also insofern nehme ich mal an, dass es eher ein PA-Unfall ist.
Aber man weiß es nicht.
Aber es ist ein Präzedenzfall.
Das Apple scannt jetzt Inhalte auf euren Geräten.
Vielleicht, dass sie vorbereitet und dafür, dass sie auch in China, den Markt weiter
öffnen wollen.
Das machen sie ja, das machen sie ja auch sowieso schon immer.
Also man kann ja auch in der Fotos-App irgendwie nach, weiß ich nicht, Hund gucken oder nach Personen oder sonst irgendwas.
Und da ist tatsächlich, das ist halt die gute Technik sozusagen, die da verwendet wird.
Und ja, man kann sogar.
Aber auch da sind viele Sachen falsch einsortiert.
Ja, aber sie sind ja auch halbwegs schnell und so.
Man kann auch nach Vaccination oder so suchen und dann findet es den Impfpass, wenn man den fotografiert hat und so.
Also das ist tatsächlich, also da machen sie auch wirklich das gute Zeug.
Und machen das halt auf dem Gerät selber.
Aber genau, nur halt, wenn man selber sagt, man hätte das gern und ja, und halt es wird auch nicht an irgendwen geschickt.
Und jetzt ist das natürlich eine andere Sache.
Wenn es jetzt irgendwas von den verbotenen Bildern findet, dann sagt es irgendwie, dann petst das.
Die gleichen verbotenen Bildern.
Ja.
Mit den False Positives.
Genau, und wir wissen auch, dass es da welche gibt, ja.
Also das ist natürlich alles sehr unangenehm.
Und das wäre dann schon ein Präzedenzfall, weil das haben sie bisher nicht gemacht.
Na gut, mal sehen, wie sich das entbietet.
PR-mäßig ist es auf jeden Fall ein mittleres Design.
Du hast das von deinem Impfpass gesagt.
Das heißt, du bist auch jetzt durch, endlich.
Vielleicht.
Ich bin schon lange durch.
Ich auch jetzt seit einer Woche.
Yay!
Tja.
Also hier auch nochmal der Aufruf an alle Zuhörer, lasst euch bitte impfen.
Ja.
Das ist eine gute Idee.
Wie viele haben wir jetzt verloren?
Die Zuhörer
will ich.
Es gab so einen tollen Rand-Post von Linus Torwalz da, glaube ich auch.
Ja, der sagt auch, lasst euch impfen, ihr Trottel.
Ja, genau, der braucht der Torwart.
Ja, Linus Torvalds benutzt noch mehr ausgewählte Wörter.
Um das zu umschreiben, sagen wir es mal so.
Ja, aber inhaltlich doch, ja, ja.
Inhaltlich war das Zusammenfassung, ja.
Ja, haben wir noch Python-News?
Ja, also eine News, die so ein bisschen anschließt an unsere letzte Episode zu Packaging, ist, dass tatsächlich, das weiß ich vielleicht schon länger klar, aber mir war es halt noch nicht klar, ab drei Python 3.111 wird DIS-Tutils halt deprecated.
Und das heißt, man muss sich da an der Stelle dann halt mal was überlegen, was man dann so tut.
Aber es gibt auch so viele Alternativen.
Ja.
Diverse Alternativen.
Also die Pakete, die jetzt halt so ein richtiges Problemchen bekommen, sind halt sowas wie NumPy und SciPy und so, weil die haben nämlich, die Erben nämlich von Distutils und haben da Extensions für gebaut und damit bauen sie halt alles.
Ja, okay.
Und ja, also die gucken sich gerade andere Sachen an.
Und tatsächlich gibt es da, also haben sich zum Beispiel CMAC angeguckt oder halt auch Mason heißt das irgendwie.
Und tatsächlich, also ich manchmal, also sogar relativ häufig, ich habe ja hier so ein M1 Mac auch und da passiert das durchaus, also wenn die Python-Version hochgeht oder so, ist es eigentlich immer so, dass wenn ich dann Projekte habe, die abhängig haben zu NumPy, Appandas oder so, dass das ganze Zeug kopiliert werden muss.
Weil meistens sind das Update von Python halt schneller bei mir, als die Wheels draußen sind.
Und dann muss ich das halt kompilieren und dann denke ich mir so, oh nein, ah, jetzt dauert das wieder ein paar Minuten.
Und tatsächlich dauert das bei NumPy, glaube ich, sieben Minuten irgendwie, mit dem klassischen jetzt des Utils.
Und tatsächlich aber auf Mason-basierten, hatte jetzt jemand schon, ich habe leider einen Namen vergessen, angefangen damit rumzuexperimentieren, dauert es halt irgendwie noch vier Sekunden oder so.
Also es ist hauptsächlich irgendwie Bauzeit, die da benötigt wird.
Also insofern, mal gucken.
Könnte sein, dass es alles schneller wird demnächst, ja.
Das wäre doch ein sehr positiver Effekt von dieser Deprecation.
Genau.
Und ansonsten, ja, ich glaube, 311 ist in der Beta.
310 ist in der Beta.
Ich glaube, jetzt um den drehenden Richtung war das.
Genau.
Die Zahlen gehen so schnell hoch.
Ja, ja.
Freu mich schon.
Ich habe mal den GitHub-Copilot, den wir irgendwie auch schon mal kurz erwähnt hatten, ausprobiert.
Da habe ich jetzt auch eine Bita-Einladung bekommen.
Ich muss sagen, das ist echt toll.
Also ich habe noch nie so einen super Effekt von einer KI angefangen.
Ich finde es echt nice.
Ich gebe mal ein, also ich habe jetzt die BS-Code-Extension dafür benutzt, sowas wie Define Ends, Fibonacci oder sowas und dann warte ich auf das Autocompletion und dann schreibt ihr mir die komplette Funktion inklusive Doc Strings und Type-Anotations als Typend und ich drücke einmal Tabulator und es ist fertig.
Und das geht halt auch für Sachen, die ich selber schreibe.
Wenn ich jetzt eine Klasse schreibe, verschiedene Methoden nehme, beispielsweise irgendwie HTTP-Methode.
Ich habe jetzt irgendwie ein Get geschrieben, ne, irgendeine Klasse, Define, Get, bla bla bla.
Und danach fange ich an mit Define und dann steckt er mir jetzt nichts vor Post zu definiert.
Und zwar auch mit genau den richtigen Parametern und so.
Das sind solche Sachen.
Das ist halt einfach, der lernt halt aus seinem eigenen Code raus und das ist, wow.
Also ich bin wirklich beeindruckt davon, was das so macht.
Also das ist so ein bisschen, man braucht keine Snippets mehr, ja, wenn man irgendwie Snippets-Sammlung hat, sondern man nimmt halt einfach dann das individualisierte Snippet und das ist echt mächtig, glaube ich.
Also mir hat das schon echt Zeit gespart zwischendurch.
Ich weiß gar nicht genau, auf welchem Modell ist das GPT-3?
Ja, ja, das ist GPT-3.
Ja, also da geht einiges.
Also ich meine, sowieso, also das ist vielleicht auch noch ganz interessant.
Es ist so ein kleiner Abschweif, aber vielleicht ja auch nicht so uninteressant.
Ich meine, Text ist ja im Grunde deutlich, also es dachte man ja aber, es ist irgendwie oder Sprache, ist halt schwierig, aber tatsächlich ist das irgendwie einfacher als andere Probleme.
Und wisst ihr, wie diese Modelle trainiert werden?
Nein.
Da kann man halt, das nennt sich, also das ist halt etwas, was sich halt männlich einbürgert.
Der Begriff dafür nennt sich Self-Supervised Learning.
Und zwar deswegen, weil man halt zum Beispiel auf Text relativ gut Modelle trainieren kann, ohne irgendwelche gelabelten Daten haben zu müssen.
Was man ja normalerweise ist, ist immer das Problem bei, irgendwie, wenn man so überwachte Modelle, also so in Anführungsstrichen normale Machine Learning-Modelle halt trainiert, dann braucht man halt Trainingsdaten und damit meint man üblicherweise halt Daten, wo man Labels angeschrieben hat, wie zum Beispiel jetzt, wenn man jetzt Bilder hat, sowas ist ein Hund, das ist eine Katze und das ist, weiß ich nicht, irgendwas dazwischen oder so.
Und bei Texten hat man das ja auch, da gibt es dann ein klassisches Problem wie Textkategorisierung, da hast du halt einen Text und dann steht halt zum Beispiel so diese News, Reutersartikel, dann steht dran, das ist jetzt Sport oder das ist Politik oder das ist halt irgendwas anderes.
Cool wäre ja so das Label wie, will ich lesen, will ich nicht lesen.
Kann man auch alles machen.
Spezifisch für dich, Damit.
Wenn du, wenn du da Trainingsdaten hast, dann kannst du Modelle drauf trainieren, die dann auch wahrscheinlich halbwegs gut funktionieren sollten.
Also das geht alles.
Aber das Problem ist natürlich, dass für die meisten Probleme, die man so hat, hat man halt eben keine Trainingsdaten.
Und das Erstellen von Trainingsdaten ist halt so aufwendig, dass sich das dann meistens nicht lohnt, das zu machen.
Wie viel braucht man denn da ungefähr?
100.000?
Also kommt darauf an, wie gut es sein soll.
Und dann entsprechend, weil halt unter Umständen schon Millionen von Beispielen oder so und das ist dann halt doof, weil das ist einfach zu viel.
Die meisten Leute haben so viele Beispiele gar nicht, ja.
Nee, genau.
Also einmal, du hast gar nicht genug Beispiele, um sie labeln zu können, dann musst du die erstmal besorgen, dann musst du es auch noch irgendwie labeln, dann hast du Fehler in den Labels, weil halt die Leute das nicht perfekt gemacht haben und dann musst du das irgendwie kontrollieren und dann schwuppdiwupp, hast du irgendwie so ein Redaktionssystem und eine Redaktionen, eine technische Redaktion und dann Prozesse und keine Ahnung und Abstimmungen und das kostet ein Schweinegeld und das macht dann halt keiner so einfach so.
Sondern nur, wenn man es halt wirklich, wirklich braucht.
Und ja, aber man kann halt aus Text auch lernen, ohne diese ganzen Geschichten haben zu müssen.
Also, das ist seit es gab ein Paper 2017, ist das, glaube ich, irgendwie Attention is all you need.
Da wurde halt diese Transformer-Architektur eingeführt.
Und diese Dinger funktionieren auf Sprache halt total super.
Und die funktionieren so, dass man quasi Texte nimmt und lässt halt jetzt Wörter weg aus den Texten.
Und lässt das Modell jetzt vorhersagen, okay, welches Wort gehört denn an die Stelle?
Und dann bestraft man das, dann sozusagen hat man halt Feedback.
Wenn das Modell jetzt ein anderes Wort, als da stand, vorher hersagt, dann sagt man, okay, das war jetzt falsch.
Und dann kann man halt irgendwie ein Gradient bestimmen, in welche Richtungen müssen sich die Gewichte ändern von dem Modell und dann propagiert man die halt zurück und dann ändert man das Modell ein bisschen in die Richtung, dass es das halt beim nächsten Mal besser macht.
Und das macht man dann ganz oft und dann kann es halt aus einem Text, ohne dass man da irgendwelche Labels explizit für bräuchte oder so, Dinge lernen.
Und zwar fast alles.
Und das ist halt das Interessante.
Das ist wirklich gut.
Weil man kann halt Text, man kann das gesamte Internet nehmen.
Und dann lernt es halt lustigerweise eben nicht nur irgendwie so stumpf, welches Wort da die entsprechend höchste Wahrscheinlichkeit hat, da zu stehen, sondern um das gut machen zu können, lernt es halt auch eine ganze Menge Konzepte und wie Dinge in Verhältnissen stehen und solche Sachen.
Ach, auch Kontext tatsächlich.
Das ist halt spannend.
Also zum Beispiel, das Plugin schafft das halt auch, Kommentare richtig zu schreiben.
Das heißt, ich fange mit einem Kommentar an, zwei Worte und das macht einen relativ guten Vorschlag, für was da stehen sollte.
Ja, ja, ja, genau.
Und das ist eine Geschichte, die man dann halt auch machen kann, dass man sagt, okay, so das ist ein Text, der Rest ist halt Lücke, dann füll mal.
Und dann kommen da auch schon ganz interessante Geschichten bei raus.
Also man, also wenn sich diese generierten Texte anguckt, dann ist es halt schon immer so, dass man irgendwann wird so leicht absurd oder sehr verdreht irgendwie und merkt so, okay, so ganz, schon so ein bisschen neben der Spur.
Ja, aber man kann es halt auch schnell kaputt
machen, wenn man dann auch so ein bisschen, oder?
Wenn man halt das so ein bisschen kalt.
Kann man es da schnell kaputt machen, dann kannst du mal so.
Ja, ich habe noch was dazu gelesen, was in eine andere Richtung geht, dass es jetzt wohl eine große Anzahl inzwischen von wissenschaftlichen Veröffentlichungen gibt, denen man durch Analyse ansehen kann, dass sie eben nicht von einem Menschen geschrieben würden, sondern von einem neuronalen Netzwerk.
Und die Technik, die die da verwendet haben, die ist total witzig, weil diese Netzwerke für so Paper-Generierung und für Textgenerierung generell, die sind, die werden wohl bestraft, wenn sie Plagiate erzeugen.
Weil das willst du natürlich nicht, ja, du willst natürlich nicht einen Paper einrechnen, was dann als Plagiate abrechnet.
Und deshalb wählen die sehr viele Synonyme.
Die sprechen sehr viel in Synonymen.
Und auch eben so Fachbegriffe werden dann oft in Synonymen genommen.
Das nette Beispiel, was ich erkenne, war eben, dass da die Paper über Big Data, die haben die ganze Zeit über Colossal Information gesprochen.
Was sie eben kein normaler Mensch schreiben würde.
Und dann haben sie eben gesucht, wie oft dieser Begriff Colossal Information in Papern vorkommt und die dann eben genauer angesehen und die waren alle, hatten eben alle diese Anzeichen von erzeugten Papern.
Und das ist so ein bisschen jetzt quasi die Kehrseite von Copilot, dass die eben nicht nur, man muss es dann trotzdem noch für was Gutes einsetzen und nicht für.
Ja, da müssen wir
schon das vorher positiv beitragen.
Ja, aber genau, was ich eigentlich, was ich noch erwähnen wollte, war, genau, man kann jetzt halt sozusagen Modelle trainieren auf allen Texten, die es im Internet gibt und die lernen halt tatsächlich da auch Dinge dann raus und das ist natürlich total super.
Und das geht bei Sprache vor allen Dingen deswegen, weil man halt eine endliche Anzahl von möglichen Füllern sozusagen für die Lücken.
Was?
Noch an Chomsky würde dir widersprechen, Jochen.
Ja, ja, gut.
Aber man kann sich da ja beschränken, kann ja sagen, okay, meine Sprache hat nur 20.000, 30.000 Vokabeln und das war's.
Und so größer ist mein Vocabulary einfach nicht.
Ja, okay.
Und indem man nur ein Wort rausnimmt, ist natürlich klar gewesen.
Und unter denen wird auch eins sein, das hinreichend nah dran ist.
Und dann kannst du eben allen Worten eine Wahrscheinlichkeit zuweisen.
Du kannst halt sagen, okay, das ist jetzt sehr, sehr unwahrscheinlich und das ist jetzt irgendwie, das geht.
Alle sehr unwahrscheinlich.
Es gibt ein bestimmtes Wort wie F, das, was überall hin passt.
Ja, klar.
Aber das Modell ist dann halt auch, das Modell, das damit trainiert wird, passt dann aber nicht mehr überall hin, wenn du das als akzeptiert.
Ich kenne so Leute.
Jedenfalls, genau.
Also mit Sprache geht das total super.
Und eben, Co-Pilot ist halt dann quasi auch eine Folge.
Das Tolle ist, dass man jetzt Modelle, die darauf trainiert sind, kann man jetzt mit ganz wenig Trainingsbeispielen auf das Problem sozusagen, dass man wirklich, dass man wirklich hat, adaptieren.
Also da braucht man dann nur noch ein paar Trainingsbeispiele, also nicht mehr viele.
Ja, ich glaube auch, also er macht das tatsächlich anhand des Reposites, was du gerade auf hast.
Kann er schon gucken und kann da schon dann die Completion zum Beispiel oder die Vorschläge anpassen auf das, was du da gerade machen willst.
Und das ist schon echt wow.
Naja, und das ist halt natürlich total toll, weil das dann, das dann halt bedeutet, dass du im Grunde dieses Trainingsproblem, Trainingsdatenproblem loswirst.
Und ja, eine ganze Menge Anwendungsfälle plötzlich von zu aufwendig, unlösbar, lohnt sich nicht, in Richtung, ja, kann man schon mal probieren wandern und dann ist es natürlich toll.
Und ja, also da wird es hier eine Menge interessante Anwendungen geben.
Also gerade für die ganzen Frauenprogrammiere unter uns.
Also das ganze Zeugst du mal rum, das geht halt einfach jetzt viel automatisierter.
Die Schwierigen sagen es mal immer noch selber rein.
Das ist schlecht für die Auftragsprogrammiere.
Finde ich nicht cool.
Ja, das kann schon sein.
Ja.
Aber genau, das Problem ist aber jetzt, dass man das nicht machen kann für, also was halt, also man würde, wäre sehr viel weiter, wenn man das jetzt auch für zum Beispiel Bilddaten machen könnte.
Also, und tatsächlich ist es wohl so, dass es da ein, gibt es auch inzwischen Forschung zu, das ist halt tatsächlich der Weg, also man hat sich ja das oft lange, oder ich erinnere mich daran, dass es mal völlig unklar war, wie das eigentlich funktioniert, wie lernen Kinder eigentlich sozusagen so schnell Dinge, man versteht es nicht.
Sie sehen eigentlich zu wenig Trainingsbeispiele für das, was sie da lernen.
Und tatsächlich lernen sie ja auch, also auch sowas, was einem die Forschung sagt, man schwierig, manchmal Schwierigkeiten hat das einfach so zu akzeptieren, aber die sagt halt, ja, also das meiste, was Menschen so lernen, lernen sie halt so in den ersten neun Monaten und alles, was danach kommt, ist halt so, naja Gott.
Also ich meine, so Details.
Also die wesentlichen Dinge sind bis dahin gelernt.
Dann fragt man sich ja, wie machen die das denn?
Ich meine, Kinder in dem Alter verstehen einfach gar nichts.
Die kennen auch keine Worte für nichts.
Wieso können die denn so viel lernen?
Wie soll das gehen?
Das ist irgendwie alles seltsam.
Und tatsächlich ist es wohl so, dass die halt auch so eine Art Self-Supervised Learning machen und quasi genau das gleiche Prinzip irgendwie, also sie haben sehen halt was und Dinge passieren und dann betrachten sie das sozusagen als eine Art Lückentext und füllen das dann halt und das funktioniert.
Genau, das ist das Ego, was das dann macht.
Keine Ahnung.
Ja, aber da zieht das dann irgendwo aus dem Erd da, irgendwelche Informationen und Stoff das dann dazwischen.
Und deswegen hast du ja auch so, ich weiß nicht, ob ihr es kennt, wenn ihr irgendwo müde seid oder sowas, dann werden bestimmte Sachen ja auch einfach ersetzt.
Der Kopf macht das ja sehr gerne, dass der bestimmte Flecken, die nicht so ganz klar sind, dann mit Sachen überschreibt.
Also einige Leute, die haben dann auch innere Stimme, die dann auf einmal selbst vervollständigt, die sie nur so hype gehört haben.
Oder das kannst du auch mit optischen Informationen machen oder mit anderen optischen Signalen.
Und das ist halt super spannend tatsächlich.
Und wenn das halt self-supervised learning ist, dann ist ja auch klar, dann hast du so ein Lückenbild.
Das ist so ein bisschen so, du hast ein Foto, da fehlt ein Teil und dann wird das automatisch ersetzt.
Das ist ja spannend, wenn die KI das kann, dann kann man sagen, machst du ein Hochzeitsbild von dir, dann kannst du irgendwie deinen Partner rausschneiden, dann kannst du den idealen Partner auf einmal sehen.
Ah ja, und so ist also dieses Python-Import-System entstanden.
Das ist ja spannend.
Nein, nein.
Nur ganz kurz, also das, was halt momentan nicht geht, was man nicht hinkriegt, was halt total toll wäre, wenn man es irgendwie hinkriegen würde, also vielleicht hat ja irgendwann jemand eine Idee, ne?
Also es ist halt das große, ungelöste Problem an der Stelle, ist halt, wenn du jetzt ein Bild aus einem, einen Teil aus einem Bild rausnimmst und sagst, so, das ist jetzt leer.
Also einmal, man kann halt irgendwie die Menge an Bildern, die halt an der Stelle möglich werden, nicht aufzählen, nicht so richtig.
Und dann ist es so, selbst wenn man sich Einheit ist, selbst wenn man sich irgendwie beschränkt, weiß man nicht, so jetzt hat man zwei Sachen, die eigentlich offensichtlich nichts damit zu tun haben mit dem Bild, das man eigentlich an der Stelle gerne hätte.
Welche Wahrscheinlichkeit weist man ihnen zu und wie ist der Gradient in welche Richtung?
Vielleicht braucht man da den Kontext für, weil wenn du einen Kontext hast, in dem das drumherum gestellt werden soll, der halt selber ein Objekt ist, das viele schiene Informationen beinhaltet, dann ist es besser, diese Menge an abzählbaren Elementen zu bilden und das entsprechend herauszusuchen mit der höchsten Wahrscheinlichkeit.
Das heißt also, ohne Kontext ist das wahrscheinlich nicht so einfach möglich, dass du einfach so ein Bild machst, das dann gut trifft.
Aber wenn du Informationen über den Kontext hast, in dem du dieses Bild ersetzen möchtest.
Also der Punkt ist eher, das ist ja möglich.
Also du kannst ja durchaus ein Modell trainieren, was dann irgendwas vorhersagt an der Stelle.
Die Frage ist nur, welchen Wert hat das, was es jetzt vorher gesagt hat?
Hat das jetzt die Wahrscheinlichkeit 0,376 oder 0,652?
Und das macht ja einen Unterschied fürs Training.
Aber es ist halt völlig unklar, wie man da die Wahrscheinlichkeit ausrechnen soll.
Ja, vielleicht braucht man dafür echt einen Kontext für das, der es eingesetzt werden soll.
Das ist, glaube ich, gar nicht so.
Ja, also das ist auf jeden Fall, wenn da jemand eine Idee hat, voll gut.
Das war jetzt auch gerade wieder so ein Ding, was halt passiert, wenn man halt den Kontext nicht hat, dann passiert sowas wie ein Relative Import Beyond Top-Level Package oder so.
Oh, okay.
Ah, das
ist so ein Syntax-Fehler quasi.
Ich sehe schon, es gibt eine gewisse Abschüssigkeit in eine bestimmte Richtung.
Ja, Import-System ist auch voll interessant.
Na gut.
Ja, Entschuldigung, es war gerade ein Versuch, da so ein bisschen hinzukommen, weil wir wollten ja über das Import-System tatsächlich reden und wie man das in Python macht.
Und ich glaube, als Basis irgendwie das so ein bisschen zu verstehen, es gibt einen super tollen Blog, den ich auch erst letztens entdeckt habe, der 10.000 Meters heißt, der irgendwie auf Hacker News nochmal gefeatert worden ist.
Und da hat ein Mensch namens Viktor Skorzdow, wenn ich ihn richtig ausspreche, einen Artikel geschrieben, wie das Python-Import-System funktioniert.
Und das hat ja so ein bisschen erklärt, das ist sehr spannend zu lesen.
Packen wir auf jeden Fall in die Shownotes.
Und ja, wie funktioniert denn das eigentlich?
Was ist denn das Python-Import-System eigentlich?
Ich habe diesen Artikel auf Hacker News gesehen und auch die Diskussionen dann so ein bisschen angeguckt und da ist mir aufgefallen, dass das doch tatsächlich erstaunlich viel komplizierter ist, als man das so denkt oder als man das so im Kopf hat.
Was mir gar nicht so aufgefallen war, weil ich offenbar nicht alle Features benutze, die das E-Star so gibt.
Also vielleicht ganz
kurz, bevor wir darauf einsteigen, was ist denn überhaupt das Problem damit oder könnte das sein?
Oder wir haben irgendwie so eine Story gehört, dass man lange dauert, wenn man doof sein kann und genau.
Worum geht es denn da überhaupt?
Und warum braucht Python ein Importsystem überhaupt?
Das ist ja auch eine spannende Sache.
Weil in anderen Sprachen ist das ja anders gelöst.
Und zum Teil besser und zum Teil schlechter.
Ja.
Wer will anfangen?
Also ich würde sagen, ja, vielleicht kann man ja genauso anfangen wie der Artikel.
Was passiert denn, wenn man sagt Import M?
Warum sagt man das denn überhaupt ja auch?
Naja, weil.
Warum sagt man Import M?
Ja, es gibt natürlich Build-Ins, aber nicht alles sind Build-Ins und manchmal möchte man halt irgendwo Funktionen oder Klassen oder sonst irgendwas verwenden.
Oder man möchte einfach seinen Code trennen und nicht alles in eine einzige Pfeile.
Also man möchte halt irgendwas verwenden, was nicht in der aktuellen Datei definiert ist.
Und jetzt könnte ich verschiedene Dinge.
Ich könnte mir die Datei nehmen und sie e-valen.
Könnte ich machen.
Ja.
Wäre auch möglich, oder?
Wäre auch, würde er auch
ein bisschen, oder?
Effekt irgendwie.
Ja, genau.
Aber das überschreibt dann natürlich manchmal Sachen, wenn ich jetzt irgendwie zum Beispiel da drin halt, wenn ich jetzt halt einen aktuellen.
Ja, vor allem, wenn man das rekursiv macht, weil das müsste dann auch immer weiter funktionieren.
Ja.
Wenn man so Counter-Variablen hat oder so, die sind dann wahrscheinlich hinterher anders.
Vielleicht, ja, vielleicht.
Ja, oder auch Namen, die einfach gängig sind, werden vielleicht eventuell überschrieben.
Ja, aber das ist ja bei Python macht er ja auch irgendwie sowas, ne?
Das macht ja so ein Name-Space wieder.
Ja, genau.
Das müsstest du dir
dann, also wenn du einfach die Datei lädst und ausführst, also E-Ware drauf machst, dann brückst du halt erstmal alles in die Hand.
Und da wäre dann hätte man dann auch wieder das Problem mit dieser Rekursion, die müssen wir auch irgendwie lösen, weil du musst ja dann eventuell noch mehr Sachen derweil importieren und e-wählen und vielleicht hast du ja sogar das Problem, dass du es zyklisch machst.
Aber das Problem haben wir ja in Python auch, das Problem
haben wir in Python auch, ja, aber müssen wir mal überlegen, wie das das macht.
Aber in anderen Sprachen, um da noch kurz drauf anzugehen, braucht man das ja nicht.
In Java oder in C<unk> macht man es ja nicht, dass man einfach andere Dateien da rein kopiert, weil da ja die Organisation anders ist.
Da braucht man ja quasi keine Objekte in der Hand, sondern nur einen Verweis auf die entsprechenden Stellen im Code.
Das heißt, bei denen funktioniert das Importsystem halt, weil das während des Kompilierens passiert, deutlich anders als in Python.
Ja, ich überlege gerade, wo da die Unterschiede sind.
Also wenn ich in C sage include, ja, das wird einfach dann so getan, als wäre das eine Datei.
Genau, aber wenn du, wenn du zum Beispiel in C inkludierst ja normalerweise nur Punkt H-Dateien.
Und da sind ja keine Definitionen drin, da sind ja nur Deklarationen drin.
Da ist nur, da steht nur drin, es gibt etwas, was heißt so und so.
Und das ist das Einzige, was du an der Stelle da reinkriegst.
Das Zusammenführen, was dann tatsächlich der Code ist oder was diese Werte sind, das passiert erst später im Link-Vorgang, wenn du schon alles kompiliert hast.
Und diese Phasen gibt es bei Python ja einfach überhaupt nicht.
Bei Python gibt es ja nur die Phase Ausführen.
Und zu dem Zeitpunkt brauchst du dann jetzt.
Und was viele Leute vergessen, wenn du Define schreibst, wenn du eine Funktion definierst, wenn du eine Funktion erstellst, dann ist das Code, der ausgeführt wird.
Das ist ein Befehl an Python und der heißt, merk dir mal, unter dem Namen, keine Ahnung, Fun.
Ein Code-Objekt, was folgende Eigenschaften hat.
Es ist Callable und dieser Callable hat folgende Parameter und dann steht der Code drin und so weiter und so fort.
Und auch bei Class, ja, wenn du Class als Schlüsselwort, wird ja erstmal alles ausgeführt, was da drin ist.
Das heißt, du kannst da prinzipiell Code drin haben, der Sachen tut, was ja auch an vielen Stellen sehr wichtig ist, was du aber in anderen Systemen nicht hast.
In der Java und in der C.
Hast du das nicht, das wird nicht ausgeführt.
Es wird zum Teil ausgeführt bei C, weil du da diesen komischen Pre-Processor hast.
Und weil der auch so konstant Optimizations versucht schon mal zu machen.
Aber generell wird C-Code erst ausgeführt, wenn du das Programm startest.
Und das ist bei Python.
Ja, also diesen Schritt des Kompilierens gibt es ja bei Python nicht.
Der ist ja da so ein bisschen innen drin.
Das heißt, du kannst auch mit Import auch Sachen ausführen.
Was manchmal komisch ist und manchmal gewünscht und manchmal überraschend.
Ja, also das ist manchmal, also tatsächlich, wenn Sachen importiert, dass dann halt alles in dem Modul ausgeführt wird, was auf dem Top-Level ist, das ist halt schon manchmal eher überraschend und dann, ja.
Warum passiert das denn auch?
Warum wird das denn ausgeführt?
Also wenn man jetzt einen Import schreibt, Import M von irgendwo, was dann einfach.
Einfach nur Import M, also wirklich nur diese Zeile Import M.
Was passiert dann?
Ja, das ist eine gute Frage.
Und auf den ersten Blick ist es, ist es so, finde ich, so ein bisschen offensichtlich, was da passiert.
Und auf den zweiten Blick ist es dann tatsächlich doch nicht so offensichtlich, wie eben dieser Artikel, glaube ich, uns allen demonstriert hat.
Also für mich bedeutet Import M, suche eine Datei, die m.py heißt und gib mir den Inhalt davon als Modul.
Oh, das wäre aber ein Skript.
Und wir können auch ein Modul laden, was halt, wenn ein Modul heißt, das M heißt, dass dann ein Verzeichnis ist oder sowas?
Oder was ist ein Modul?
Das wäre dann
wieder was anderes, oder?
Aber ein Verzeichnis ist ja auch nur so eine Art Datei.
Verzeichnis ist ja auch nur ein Verweis auf die InitPi-Programm.
Also es gibt
Skripte, Module und Packages.
Und was ist denn überhaupt der Unterschied?
Was ist ein Skript, was ein Modul, was ist ein Package?
Das ist schwer
zu sagen.
Ich finde es schwer zu sagen, weil für mich dieser Unterschied wirklich minimal ist.
Das eine ist halt eine Datei und das andere ist ein Verzeichnis, aber das Verzeichnis selber hat ja keinen Inhalt und deshalb tut man so, als ob die InitPie, die da drin ist, das der Inhalt dieses Verzeichnisses ist.
Genau, der Init Pie kann man auch sowas wie All dann definieren.
Das heißt, wenn man zum Beispiel sowas wie Inport-Assetz
überall, kannst du auch eine einzelne Datei machen.
Kannst du überall definieren.
Ja, okay.
Kannst du auch Slots definieren?
Das ist auch, kannst du auch überall machen.
Ein Slot?
Ja, das sind solche Sachen, die beim Import mitgebracht werden sollen.
Genauso wie All, ja.
Wenn du All definierst und dann machst du vom M Import-Stern, dann kriegst du alles das, was in All drinsteht.
Also Unterstrich, Unterstrich, All, Unterstrich, Unterstrich, um es jetzt mal hier korrekt zu sagen.
Dann, dann, all, dann, dann.
Das ist ein sehr guter Mechanismus, den sieht man sehr selten, weil Import Sternen ja so
verpönt ist.
So gerne gesehen wird.
Es riecht.
Das hatten wir schon in der ersten Vorlesung quasi in Informatik 1 hat uns unser Professor schon gesagt.
Ja, man kann Using Namespace Standard nehmen und dann kann man mal gucken, wie viele Symbole da importiert werden und es waren irgendwie 13.000 oder sowas.
Und das kannst du in Python natürlich auch machen, ja.
Kannst du auch From Stern, Import-Stern probieren, ja?
Kriegst du halt auch 100.000 Sachen rein.
Deshalb ist Import Stern, habe ich noch gar nicht probiert.
Nee, nee, Vom Stern, Importstern geht nicht.
Aber so die, so quasi, wenn du es dir vorstellst.
Importstern heißt halt, hol alles aus diesem Modul oder aus dem Package und gib's mir.
Und meistens weiß man ja gar nicht ganz genau, was da drin ist.
Meistens weiß man auch nicht, wie viel da drin ist.
Und ganz oft sind da ja dann auch lokale Sachen drin, die man eigentlich gar nicht haben möchte.
Oder Imports, die, die, die dieses Modul macht, die hast du dann auf einmal auch selber importiert.
Subdependencies quasi.
Genau.
Also wenn du in der M.py, so wie wir es jetzt eben drin hatten, wenn du da Import, keine Ahnung, Import X machst und dann machst du vom M Import Stern, hast du auch X importiert.
Weil das halt im Modul M dann schon drin ist.
Und das ist genau der Grund, warum man dies stern nicht machen soll, weil man nämlich nicht weiß, was da drin ist und man halt dann alle.
Weil du viel gab bei einem Lokal irgendwo überschreiben würde.
Und wenn mehrere Module oder Pakete dasselbe Namen definieren für irgendwas, was ja durchaus mal vorkommen kann, dann weiß man nicht mehr genau, was unter dem Namen jeweils identity ist.
Aber jetzt müssen wir ja erstmal klären, was Import überhaupt macht.
Ja, wir sprechen jetzt schon die ganze Zeit über, aber wir wissen es immer mehr.
Wir wissen aber immer noch nicht genau, was der Unterschied zwischen Modul und Paket ist.
Ja, also ich glaube, das eine ist eine Datei und das andere ist ein Verzeichnis.
Es gibt eine Datei.
Ich glaube, es ist auch irgendwie.
Ja, ich glaube, der entscheidende Unterschied ist, dass irgendwie ein Paket Submodule haben kann und ein Modul nicht.
Genau, also ich habe eine Definition gefunden, der irgendwo sagte, dann if a module name has no dots, it's not considered to be part of a package.
Aha.
Mag sein.
Ich weiß es nicht.
Also ein Paket ist halt quasi eine Sammlung von Modulen oder sowas.
Und dann irgendwie so.
Da gab es auch eine tolle Antwort drin, relative imports for the billions times oder sowas.
Ja, relative Imports, darüber müssen wir auch noch sprechen.
Ich bin ja ein großer Fan davon, aber offense bar sind die nicht so.
Gut, da kommen wir vielleicht nach.
Ja, ja, okay, gut.
Also was macht denn Import jetzt überhaupt?
Import macht, soll ich mal versuchen, soll ich mal mein Verständnis erklären und ihr korrigiert mich dann.
Von wo importiert ihr denn überhaupt?
Genau, also Import.
Erstmal sucht Import einen, also wenn ich sage Import M, dann sucht das Import-System von Python nach etwas, das M heißt.
So läuft das denn?
Ja, genau.
Und zwar auf dem Python Path.
Auf dem Path, ah.
Eine Variable, die heißt sys.pythonPath.
Sys.path.
Sys.path heißt die nur.
Okay, ich weiß, ich vergesse es jetzt mal wieder.
Jedenfalls ist da eine Menge von Verzeichnissen drin.
Und in der Reihenfolge, wie sie in diesem Path stehen, wird nach dem Namen M gesucht.
Also 0 ist, glaube ich, der aktuelle irgendwie der Datei.
Entweder vorne oder hinten, das ist immer.
Ich glaube, null der erste ist immer der, wo du gerade.
Genau.
Also die Datei, wo du gerade aufgeführt bist oder sowas.
Und dann ist halt quasi, der sucht halt dann im ersten in 1, wo und abdave und was und der erste Hit wird dann genommen.
Genau, der
erste Hit wird dann genommen.
Und in diesem Path sind immer, können ganz viele verschiedene Sachen drin sein.
Also die Installation, das Installationsverzeichnis des Interpreters und wenn man irgendwelche Environments aktiviert hat, dann sind die da alle drin.
Man kann da auch selber Sachen reintun, braucht man manchmal, ist manchmal ganz nützlich.
Ja, also da
sind einfach.
Wenn man die vielleicht Pakete haben will, die auch importiert werden können, dann muss man einfach da gucken, dass ein Dispunkt Pass quasi in der Umgebungsvariante im Vater ist.
Das ist im Wesentlichen das, was Virtual Env macht.
Er macht ein Verzeichnis, wo du deine Pakete reinlegen kannst und tut den in den
Python Path für dich.
Wichtig, dass euer Path vernünftig konfiguriert ist, wenn ihr Python nutzt.
Weil wenn die falsche Reihenfolge drin ist, dann kann das sein, dass er im Pfad von Python 2 sucht oder so, also wie es früher offenbar war.
Und dann hat er ein Problem.
Genau.
Also, und er sucht diese ganzen Verzeichnisse
durch und wenn da irgendwas drin ist, was diesem Namen M entspricht, also eine M.Py oder ein Verzeichnis, was M heißt, was eine InitPi hat, oder in Python 3 ein Verzeichnis, was das M heißt und Python-Dateien enthält, was keine InitPy hat, dann wird das als Modul importiert und in den aktuellen Namespace als Modul M übergeben.
Wir haben gerade wirklich das in Python 2 und 3, deswegen bin ich das ja interessant.
Ja, da gibt es Unterschiede.
Und da gibt es auch interessante, also nochmal ein sehr interessanter kommt mit Python 3.3, glaube ich, dazu, nämlich die Namespace-Only-Pakete.
Erklär mal.
Ja, also die gibt's.
Also früher muss man ja immer die Init-PY haben.
Ah, ja, genau.
Vor allen Dingen deswegen, damit halt nicht Verzeichnisse, die halt so heißen wie ein Standardmodul, halt das Standardmodul überschreiben.
Und man halt damit dann quasi öffentlich dazu bekennt, dass das jetzt ein Paket sein soll.
Und also sozusagen, wenn man sich in den Fuß schließt, dann muss man das auch wirklich absichtlich gemacht haben.
Und das ist aber teilweise blöd, weil oft will man vielleicht auch Dinge, die in einem Paket liegen, nicht in einem Verzeichnis haben, zum Beispiel.
Und also wenn es ein Init-PY gibt, dann ist das ja dann, jetzt weiß ich nicht mehr die Stelle, wo das irgendwo drin steht, dass da drin gesucht werden soll.
Also das Pass, ja, aber es gibt auch noch irgendwie andere Stellen, glaube ich.
Es gibt auch noch Module, die nicht da drin sind.
Also zum Beispiel die Standardbibliotheksmodule sind, also es gibt welche, die sind irgendwie in das Python-Binary reinkompiliert.
Und dann gibt es auch noch welche, die sind irgendwie woanders hingemashelt, aber die liegen da auch irgendwo rum.
Also die rein Python-Modul, die nicht zähle.
Oh Gott.
Das stimmt dazu kommen, aber es gibt auch noch Dinge, Module, die sind halt einfach nur eine Shared Library und nicht irgendwie Python.
Aber da kommen wir gleich noch so weiter.
Wurde PyCache und so weiter noch was dann kommt, aber egal.
Genau.
Aber man kann halt auch, es gibt auch Verzeichnisse und denen wird da auch gesucht, wenn da keine N-PY ist, das ist allerdings dann irgendwie weiter hinten.
Und alle, die den gleichen Namen haben, wenn da jetzt Sachen drin liegen, dann wird das zum gleichen Paket gehörig irgendwie aufgefasst und das dann so ein Namespace-Package.
So ein Namespace-Mängling.
Und dann kannst du halt auch initeren.
Also wir halten fest, einfach immer eine Init-Pile.
Ja, dann ist
es eine sichere Seite.
Aber so kannst du halt auch Dinge in einem Paket haben, die in unterschiedlichen Verzeichnissen liegen, was halt manchmal auch ganz praktisch ist.
Manchmal kann man das schon brauchen.
Ja, okay.
Okay.
Also was ist dann, das haben wir gesagt, ein Package.
Es gibt auch ein Dann-Dann-Package.
Was steht denn da?
Wann ist dann das Current Package?
Genau.
Ja, das ist das aktuelle Paket.
Das ist auch ein Top-Level-Modul oder sowas, ja.
Ja, ach Gott, ich weiß auch nicht.
Ich glaube, also wenn es ein None ist, dann ist es ein Skript.
Also vielleicht nochmal zu distinguieren zwischen Modul und Pakete oder so.
Und wenn ein Package, dann ist das nur ein Skript.
Und wenn, er sucht halt an, ob er so ein Package findet und wenn er eins findet, dann ist das Top-Level-Modul, von dem man dann importieren kann oder so.
Und wenn es das nicht gibt, dann gibt es halt auch Fehler.
Attempted Relative Import Beyond Top-Level Package.
Ja, das ist so eine Sache, die gibt's.
Passiert mir auch regelmäßig.
Echt, das passiert mir nie, das ist voll seltsam.
Doch, passiert mir nicht.
Es gibt so Sachen, die machen Menschen offensichtlich unterschiedlich.
Und das ist so eine Sache, die mache ich offenbar nicht.
Also nicht, weil ich besser bin oder weil ich irgendwie das toller kann oder so, sondern weil es einfach was ist, was ich nicht benutze.
Ja gut, aber wenn du relative Importe benutzt, aber die Sache.
Aber und vertippt man sich ja mal oder hat irgendwie.
Ja, aber
also relative Importe, jetzt müssen wir über relative Importe sprechen.
In Python 3 und ich glaube in 2.7 wurde das dann irgendwann geportet, gibt es die Möglichkeit zu sagen, from Punkt Import irgendwas.
Also vom Punkt Import M.
Oder vom Dot oder vom Punkt.
Import M.
Oder auch From Punkt M-Import irgendwas.
Und dieser Punkt heißt halt eben immer aktuelles Verzeichnis, also aktueller Pfad.
Das heißt, wenn es in dieser Installation, die ich habe, zwei Module gibt, die M heißen, dann kann ich durch diesen relativen Import genauer sagen, welches ich meine.
Ach, okay, doch, nee, das war der Unterschied zwischen Modulen und Packages.
Module haben ein Pfad dran.
Ja, ich glaube tatsächlich, das ist der entscheidende Unterschied.
Ich glaube
schon, ja.
Genau, das Top-Level-Package ist halt irgendwie doch die Sache.
Also wenn ein Package, wenn man ein Paket finden kann, also ein Top-Level finden kann, ja, mit diesem Dot-Dot, dann geht das halt ab.
Aber wenn das nun ist, weil man quasi auf der höchsten Ebene ist, dann gibt es halt so einen Fehler zurück und das ist ja genau der Grund, warum das ist.
Es kann natürlich sein, dass ich das einfach nie...
Also für mich ist einfach Punkt, ja.
Wenn ich sage vom Punkt importen, dann weiß ich, das muss im aktuellen Verzeichnis liegen.
Wenn ich sage vom Punkt, Punkt, dann weiß ich, das muss im Verzeichnis drüber liegen.
Und für mich ist das einfach eine Möglichkeit, quasi in meinem Projekt zu navigieren.
Aber ich sag mal so, das geht aber nur dann, wenn der Interpreter richtig aufgelöst ist, weil wenn du tief drin bist und dann das Skript beispielsweise manuell ausführst, relativ tief drin, dann wird er ja diesen Fehler schmeißen, wenn er
wenn du diese Datei direkt aufrufst.
Das kann man übrigens verhindern, indem man einem dann sagt, Python-m und dann dieses Modul dann innerhalb von dem Pfad aufgerufen.
Die meisten meiner Projekte sind ja aber in einem Django-Umfeld.
Und da bin ich nie in der Verlegenheit, diese Sachen direkt aufzurufen, sondern die werden dann entweder über einen Run-Server aufgerufen oder über einen Test oder über einen Command.
Auch da bin ich immer.
Ja, aber
der Pfad ist immer festgemacht an der Manage-Pile.
Genau.
Das heißt, das weiß ich.
Ich weiß, wo der Pfad.
Genau, aber das ist ja auch Python-m Package.module oder so, ja.
Genau.
Und deshalb ist das vielleicht was, was einfach in meiner täglichen Arbeit nicht so auftritt, dass ich da mich quasi fernavigiere, weil meine Projekte eben immer einen festen, eine feste Wurzel haben und darunter kann ich mich bewegen, wie ich möchte.
Ja, mir passiert das halt vor allen Dingen dann, also einmal in Paketen habe ich oft gerne Tests in einem anderen Verzeichnis.
Also da gibt es halt Tests nicht innerhalb von dem Projekt selber, sondern liegen halt in einem Tests Directory.
Wenn da irgendwas nicht richtig konfiguriert ist, dann passiert das halt schon mal.
Ja, genau, klar.
Und was mir halt auch ab und zu passiert, ist halt in Jupyter-Notebooks, weil die liegen halt auch wieder in einem anderen Verzeichnis.
Die sind halt auch irgendwo.
Genau.
Und deswegen sehe ich das relativ sehe ich das halt häufiger mal.
Also bei diesem Importer ganz interessant.
Ich glaube, das kommt dann wirklich darauf an, wenn der Name des Moduls Punkte enthält oder halt nicht.
Weil wenn der Punkte hat, dann.
Achso, wenn der Name des Moduls, also wenn das Punkt, wenn das Modul quasi m.x.y.
Genau, dann ist es halt ein paar Paket und fahrzeitig und wenn es einmal halter.
Ja, genau, aber nein, aber wenn andersrum, wenn es halt keinen Punkt mehr hat, dann muss es eigentlich schon Top-Level sein, weil dann kann es ja nicht.
Ah, okay.
Aber man kann ja jetzt auch so Dinge tun wie man sagt vom M-Import X oder so und das mit X dann.
Habt ihr schon mal Skriptnamen mit Punkten verwendet?
Also mit mehreren Punkten drin.
Das, was ich gerade jetzt überlege, ob ich eine Datei mit Punkten drin hätte, ohne also Punkt Py.
Ich glaube, dass das kann zu Problemen führen, oder?
Ich glaube
auch, dass das zu Problemen führt.
Und das würde ich auch vermeiden einfach.
Müssen wir mal ausprobieren.
Interessant, stimmt.
Das habe ich auch noch nicht gemacht.
Das müssen wir, das wird dann die nächste Episode.
Was passiert eigentlich, wenn man Punkt eingibt?
Ja, genau.
Achso, genau.
Die Form Import M ist ja noch vergleichsweise offensichtlich.
Aber jetzt hat er Jochon eben gesagt, was ist denn, wenn ich sage, From M Import X?
Genau.
Und was dann halt für mich passiert ist, er importiert erst M und guckt dann in M nach, ob es da etwas gibt, was X heißt und nimmt mir das als Import.
Aber das stimmt nicht ganz.
Weil es kann nämlich auch, man kann auch from M-Import X machen, wenn es in M gar kein X gibt.
Weil eben, wie angekündigt, wenn M ein Verzeichnis ist, was eine InitPy enthält, dann kriege ich aus dem Import M alles das raus, was in der InitPy drin ist.
Aber from M-Import X kann dann die Datei X.py sein, also Mr-X.py und die kann ich mit, die kann, also an die komme ich dran, ja, vom M-Import X.
Aber die ist nicht in M selbst enthalten.
Also wenn ich nur Import M mache, gibt es nicht M.x.
Kann so sein.
Deshalb ist es dann doch immer noch ein kleines bisschen anders.
Also man muss eigentlich immer auf die Datei zeigen, die man haben möchte.
Ja, aber genau, das fand ich auch nicht mehr, das hat mich auch überrascht, das wusste ich nicht, dass wenn man sagt, vom M-Import X, ich weiß nicht, was ich vorher gedacht habe, was ist, aber ich dachte, das macht dann halt irgendwie, holt das X da raus und dann hat man das halt im eigenen Namespace.
Aber eben, das macht halt eher sowas wie Import M, dann sagt es X gleich M.x und dann sagt es Dell M.
Und das ist halt eher so das, was tatsächlich passiert.
Und das ist auch schon so, ui, hol das.
Also wenn es nicht
geht, macht er doch was anderes, weil dann holt er sich doch noch die Datei.
Ja, ja, ja, ja.
Achso, und jetzt ist natürlich alles übrigens noch gecached, ja.
Also man kann so oft Import M machen, wie man möchte, es wird nur einmal gelesen, die Datei.
Und wo wird das dann reingeschrieben?
In das Dictionary der offenen Module.
Dictionary der geladenen Module.
Das heißt irgendwie Sys.modul.
Sys-Modules.
Keine Ahnung.
Das heißt, das muss man.
Okay, gut.
Dominik weiß es.
Dominik weiß es passiert.
Sehr gut.
Das ist übrigens auch so eine Geschichte, das kann man auch schön verwenden.
Also manchmal braucht man ja, also Singleton, ehrlich gesagt, beschütztes cooles.
Es hat einen total coolen Namen, deswegen wollen sie Leute noch nennen.
Aber tatsächlich gibt es ganz gut.
Manchmal braucht man das, ja.
Manchmal braucht man es tatsächlich.
Meistens nicht.
Meistens eher nicht.
Genau, aber Module
sind immer Singletons.
Ganz genau.
Und das ist tatsächlich die eleganteste Art, die ich kenne, wie man das hat.
Und es ist ja auch manchmal total nervig.
Ja, aber ich habe da vorher schon, also meistens habe ich dann einen Borg-Pattern verwendet oder halt irgendwas in der Richtung.
Oder manchmal halt auch, wenn ich nicht Borg wollte, sondern direkt Singleton, dann wurde es aber schon haklich.
Dann kann man das irgendwie, dann muss man schon so Metaklassen oder sonst irgendwie sowas, muss man so Dinge, wo man sich hinterher so ein bisschen schmutzig fühlt, irgendwie machen.
Und bis ich dann irgendwann mal, weiß ich gar nicht, wo ich das gesehen habe, den trickst, so dass jemand meinte, ja, ja, Module sind auch sowieso Singleton, das sind doch einfach eine globale Variable in einem Modul.
Ja, stimmt ja.
Stimmt.
Und das muss man nochmal genau erklären, warum das ein Singleton ist, wenn ich.
Aber Jochen,
wenn du dann, wenn du dann das Pattern richtig ausführen müsst, musst du dann in dem Modul noch ein Get irgendwas machen.
Ja, ja, falls das anlegt oder.
Falls jemand versucht, darum rumzukommen.
Ja, genau, eigentlich ja.
Jetzt der Dominik möchte es gerne erklärt haben.
Ja, also genau, also ein Singleton macht irgendwie, dass er guckt, ob es schon ein Objekt gibt, das dieses Typen ist und gibt das dann zurück, wenn es schon gibt, und sonst erstellt er einfach das eine, was es nur geben darf.
Ja, Singleton heißt ja erstmal nur, es gibt während der Ausführung des Programms nur eins davon.
Egal, was davon.
Und Borg ist, dass es ganz viele davon, aber die sind alle dieselben Eigenschaften.
Immer.
Dass er den Eigenschaften von
einem ändern soll.
Es ist nicht die gleiche Instanz tatsächlich.
Es kann unterschiedliche Instanzen sein, aber der State ist immer der gleiche.
Genau, das heißt, die Eigenschaften sind alle dieselben über alle Instanzen hinweg.
Ja, genau.
Okay.
Und Singleton kriegt man eben durch ein Modul einfach hin.
Also ich mache eine Datei singleton.py und da schreibe ich rein x gleich 2.
Dann mache ich Import Singleton und dann sage ich Singleton.x und das ist jetzt diese Instanz, dieses Punkt X gibt es nur genau einmal.
Weil der Python-Interpreter eben beim Import jede Datei nur einmal importiert, um es mal so zu sagen.
Wenn eine Datei einmal importiert wurde, dann liegt die im Cache und dann, wenn du dann Import Singleton sagst, kriegst du wieder die aus dem Cache.
Mit allen ihren Eigenschaften.
Das heißt, du kriegst es mit dem, du kannst es nicht ganz einfach machen, dass du diese Datei nochmal importierst.
Weil Pythonite sagt, ja, die kenne ich ja schon.
Brauche ich nicht nochmal importieren.
Also weil das Moment, also das war dieser Import, das ist ein Modultyp dann, wenn du Modul hast?
Genau, das heißt Module.
Und dieser Modultyp ist einfach die Zeichkette, keine Ahnung, von dem was ist.
Das Ausgeführte ist eigentlich der ausgeführte Code, der da drin ist, mit so einer Closure, die außenrum.
Und das wird dann doch gecastet, also was dann ein E-Wal wäre oder das habe ich ja nicht genau gedacht.
Ja, im Endeffekt macht es ein E-Wal, ja.
Aber halt ein sehr gut verstecktes.
Ja, gut.
Ich meine, Import heißt, führ mal bitte den Code in der Datei XYZ aus.
Also musste ihn irgendwie ausführen.
Irgendwo muss da ein E-Wal drin sein.
Aber es ist eben hinter so vielen Schichten versteckt, dass du es nicht siehst.
Also was der macht, ist, er lädt diese Datei.
Immer wieder und immer wieder und immer wieder.
Das heißt, wenn ich auch von mehreren Stellen.
Aber wenn ich an mehreren Stellen das habe, was ist denn dann passiert?
Im ersten Import-Singleton wird diese Datei geladen und ausgeführt.
Ja.
Und das Ergebnis dieser Ausführung wird als Module Singleton abgelegt in diesem Sys-Modules-Cache.
Und vielleicht wird dann da Py-Cache drausgebracht, PyC-Files oder so, hat das direkt da.
Ja, nee, das ist nur
eine interne Repräsentation.
Das ist halt eben ein internes, es ist eine Klasse, die heißt Module und die hat Eigenschaften.
Und wenn du dann nochmal Import-Singleton machst, zum Beispiel in einer Datei oder zu einem späteren Zeitpunkt oder in einer Schleife, wo du es tausendmal machst, dann wird nicht nochmal diese Datei singleton.py geladen, sondern dann guckt er eben in seinen Sys-Modules Cache und sagt, ah ja, den Namen Singleton kenne ich schon.
Genau, also das ist das Modul.
Beim ersten Import lädt er das tatsächlich in den PyC-File rein.
Also das heißt, er macht aus Bytecode raus, er kompiliert das quasi und führt sie aus.
Er liest das quasi einmal aus, deswegen führt das aus und macht dann einen Bytecode raus und dann schreibt er das in Py-Cache rein und von da versucht dann erstmal zu laden aus PyC.
Genau, noch einen
Schritt weiter.
Und das war jetzt ein Marshall-Object, dieses Produkt.
Nein, nein, das
Ergebnis der Ausführung ist das, was dann das Modul ist.
Der Code des Moduls kann dann schon wieder weg sein, weil den brauchst du dann gar nicht mehr.
Wenn du irgendwo ein Dev machst oder ein Glas machst, da sind dann so Baldcode-Objekte dran, weil die müssen ja nochmal ausgeführt werden.
Aber das Modul selbst, das, was in der Datei drin steht, das muss gar nicht mehr da sein.
Also wenn du einfach nur eine Datei hast, die ganz viele Sachen ausrechnet und am Ende aber nur einen Wert rauskommt, dann ist dieser Code nicht mehr da.
Es ist nur noch das Ergebnis da.
Also das Ergebnis der Ausführung dieser Datei ist dann das, was in das Modul ist.
Okay, und was wird dann in die PyC-File reingeschrieben?
Die PyC-Files sind so eine Zwischendurchoptimierung, weil die enthalten so einen vorkompilierten Bytecode und der ist schneller zu laden als eine .py-Datei.
Und das ist ein Marshall-Objekt.
Also wir hatten die ganz am Anfang einmal kurz Marshall gesagt, was ist das überhaupt?
Einmal kurz nochmal den kleinen Exkurs.
Joachim, erklär dir du doch mal.
Ach ja, damals.
Genau.
Im Grunde Marshalling ist eigentlich ein anderes Wort oder ist eines der Worte, die man benutzt, wenn man jetzt zum Beispiel einen Code oder irgendwie eine Datenstruktur seralisieren möchte in einer Liste von Buchstaben oder in einem String oder in einem Byte-Datenstruktur, die man dann halt irgendwie auf einer Platte speichern kann oder noch mit sich rumtragen.
Und da gab es zwei Module.
Die ersten waren halt Marshall, das heißt auch so, das gibt es immer noch in der Standardbibliothek und Shelf.
Shelf war schon damals nicht so richtig populär.
Also Marshall kann man noch verwenden, kann halt nur relativ wenige Datentypen und in neueren Python-Versionen verwendet man da eigentlich immer Pickel für.
Aber das ist halt im Grunde das, was es macht, wenn man sagt, vom Pickel oder wenn man sagt, ziepickel.dump, Dump S oder so, dann wird das halt ein String oder Dump in eine Datei geschrieben und dann hat man da halt eine in einen String serialisierte Form von zum Beispiel irgendwie Code.
Also mittlerweile, glaube ich, sogar Dill oder sowas, ne?
Import Dill-S-Pickel oder so, für also neuere Version.
Ja.
Als Third-Party-Package irgendwie.
Schön, schön.
Kann man auch machen.
Okay, aber ein Marschhalt-Objekt, falls ihr das irgendwo findet, ist quasi eine serialisierte Form von dem Code, der da gelaufen ist, ja.
Genau.
Okay, also jetzt haben wir aber, okay, jetzt haben wir es irgendwo geladen, haben wir erst gefunden, und was importiert ihr dann?
Was ruft ihr dann auf?
Ja, das Ergebnis dieser Ausführung.
Also Important Import.
Dann dann.
In diese Funktion kommen dann halt die Argumente rein, die können.
Ja, nee, das kann ja alles möglich sein, wenn man kannst
du auch beliebige Objekte in deine Datei reinschreiben.
Du kannst auch ein Modul machen, was einfach nur einen String enthält, wo irgendwelche Binärdaten drin sind.
Kannst du auch.
Macht man ja manchmal, weil man Testdaten braucht.
Wenn du das Modul hast, wo einfach so ein paar Strings drin sind.
Und wenn die eben ausgeführt werden, dann werden die halt so eine String-Objekt in Python mit einem Namen.
Und genau diese Sachen, also im Endeffekt ist das halt so ein Dictionary, was da drin ist.
So ein Unterstrich, Unterstrich, dict, Unterstrich, Unterstrich.
Das hat natürlich noch mehr so Attribute, ja, der Path ist da drin und der ursprüngliche Importname und die und der Doc-String wird rausgelesen und so weiter.
Also diese ganzen Sachen, die halt so passieren, wenn Python was ausführt, die passieren da auch.
Alles das, was Python langsam macht.
Alles das, was Python awesome macht.
Genau, und das Ergebnis dieser Ausführung ist halt dann das, was das Modul ist.
Das Zusammengefasste Modul.
Da gibt es Modul.doc und Modul.dikt und Modul.
was weiß ich nicht noch alles.
Punkt Name und Punkt Path und Punkt.
Punkt K-Package und Genau, also alle diese Sachen, die halt dazu gehören.
Aber das ist dann schon ein Python-Objekt.
Also es ist keine Datei mehr, sondern es ist dann ein fertiges Python-Objekt.
Und auch diese Klassen, ja, die müssen ja erzeugt werden und wenn es so Metaklassen hat, dann müssen die ausgeführt werden.
Also alles das, was da, ja, wenn, es ist quasi wie wenn man die Datei in den Interpreter eingibt und dann alles, was da rauskommt, eben zusammenfasst in eine Sache gepackt.
Also es ist eigentlich von der Organisationsebene her, finde ich, sehr sauber.
Weil alles, was in der Datei drin ist, ist dann eben als Python-Objekt verfügbar.
Und das ist auch für mich so ein bisschen der Grund, warum er das braucht, ja.
Dass ich halt einfach bestimmte Python-Objekte oder bestimmte Dinge in andere Dateien reinschreiben möchte.
Und diese Dateien sollen in anderen Verzeichnis liegen, damit ich nicht die Übersicht verliere.
Und ja.
So, das ist Import.
Und jetzt gibt es noch Import-Lib.
Ja, ja.
Das wird ja aufgerufen sogar.
Also Import wird ja Import aufgerufen, wenn man es nicht überschrieben hat.
Import ist eigentlich syntaktisch.
Genau, das kommt ja auch noch dazu.
Das ist ja in dem Artikel, glaube ich, nicht drin, aber in der Diskussion war es dann drin.
Man kann das auch überschreiben.
Man kann auch selber eingreifen in den Importprozess.
Also Dinge, die man, auf der Liste der Dinge, die man unbedingt tun sollte, ist das ganz, ganz gut.
Ein Importdekorator
weit unten.
Es gibt Import-Lib und in Python 3 irgendwas hat auch dieser Prozess, dieser Importprozess ist quasi zu einer Python-Funktionalität geworden, den man programmatisch aufrufen kann, was sehr nützlich ist.
Und dieses Statement Import M ist quasi nur noch ein syntaktischer Zucker für Importlib.
Unterstrich, Unterstrich, Import, ja, irgendwie sowas.
Das Coole daran ist, dass man eben jetzt in diesen Prozess eingreifen kann.
Und das ist insbesondere dann für zwei Sachen nützlich.
Die erste Sache, für die es super nützlich ist, da muss ich jetzt leider auf meine eigenen auf meine eigenen Dinge verweisen, da werde ich in Kürze ein Video dazu hochladen.
Kommt dann natürlich in die Show Notes.
Oh ja.
Wenn man etwas neu laden möchte, weil wir haben ja eben besprochen, wenn ich Import M mache, dann kriege ich immer das, wird es einmal geladen und dann nie wieder.
Und man ist ja jetzt oft als Softwareentwickler in so einer Situation, dass man Dateien dann verändert und die eigentlich sofort haben möchte.
Ohne dass man das Programm neu startet.
Und um das hinzukriegen, habe ich mir halt so ein bisschen einen Glue-Code geschrieben, der Dateien überwacht und wenn die sich ändern, dann wird da halt ein Re-Import durchgeführt.
Und das ist möglich durch die Funktion aus Import-Lib.
Da kann ich sagen, importiere diese spezifische Datei, auch wenn die schon mal importiert war.
Und dann wird die importiert.
Egal, ob die schon im Cache liegt oder nicht.
Ah, cool.
Ja, ich meine, der Entwicklungsserver von Jackmo, der kann sowas ja auch.
Ja, aber der macht ja einen Neustart.
Der macht tatsächlich einen Neustart, naja.
Der hat so einen Watcher-Prozess und dann schießt er einfach den Prozess ab und startet einmal neu.
Achso, ich weiß gar nicht, wie das, wie das.
Gut, das ist ja, oh mein Gott, das ist ja schrecklich.
Ja, aber es hat auch Vorteile, weil dann halt alles auf Null zurück ist.
Wie ist das denn bei Jupyter?
Ist das ja auch so?
Da kann ich ja auch im Import sagen, ob ich das jetzt möchte, dass ich das nochmal importieren will, wenn es sich ändert.
Macht so einen Re-Import.
Genau.
Da gibt es eben diese Jupyter-Magik, die du sagen kannst und der benutzt tatsächlich Import Lib und macht Reimport.
Ah, okay.
Neustarten wäre auch blöd.
Ja.
Es geht ja auch geht ja auch an der Stelle einfach gar nicht.
Zum einen, weil der Prozess ja da läuft und zum anderen, weil du ja die anderen Zellen nicht kaputt machen willst.
Du hast ja die Zellen immer noch.
Ich hatte übrigens tatsächlich jetzt letzte, vorletzte, nee, letzte oder vorletzte, nee, ich glaube letzte Woche und ich erinnere mich schon nicht mehr dran, den Fall, wo ich tatsächlich Import Lib gebraucht habe und habe halt die Importfunktion überschrieben.
Was hast du damit gemacht?
Ich habe einen Pull-Request bei Wactail Media eingereicht, weil es nicht mit Wactail 213 kompatibel war.
Und Wactail, ja, da gibt es Tests und das Problem ist jetzt, dass man jetzt in den Test, man möchte die Tests ja, also da ist dann, okay, ich fange einfach mal von der Seite an.
Es gibt im Code so Dinge wie, probier das mal zu importieren.
Wenn es schief geht, mach was anderes.
Weil zum Beispiel diese Telepath-Bibliothek gibt es erst ab Wacktile 213.
Okay.
Und da sagt man halt, probierst du.
Auf lokale, ich benutze das ganz häufig für lokale Settings, ja.
Irgendwo eine LocalSettings.py und dann macht man halt try Import LocalSettings.py.
Ja, wenn es nicht Exp-Path.
Genau, genau.
Und jetzt möchte man das aber testen.
Jetzt möchten wir testen, dass, wenn, und es gibt da, also war noch kompliziertere, wie gesagt, das habe ich jetzt wieder vergessen, weil es ein bisschen kompliziertere Logik, die davon abhängt, ob man es jetzt geschafft hat, das zu importieren oder nicht.
Und jetzt, wie willst du das testen, ob jetzt wirklich der richtige Code ausgeführt wird?
Also der Code ja zum Beispiel dann nur so ein Dummy-Objekt anlegt.
Wie willst du testen, ob das funktioniert hat, wenn du nicht dann noch eine andere Paketversion installieren willst, was du im Test auch nicht gut machen kannst.
Wow, und dann habe ich da einfach quasi Importfunktionen überschrieben und dann in der Import-Funktion gucke ich halt so, wird gerade versucht, das da zu importieren.
Ja, wirklich gut.
RaceException, ja.
Und dann Race-Import-Error.
Und dann kann man halt testen, okay, und ist jetzt wirklich das Dummy-Objekt?
Ja oder nein?
Und dann hat man einen Test dafür.
Ja, aber fast.
Das ist ja spannend, aber das ist auch ganz schön tief eingegriffen in die
Jochen auch aufgenommen und wir müssen jetzt aber suchen, welcher Folge kommt.
Du kannst uns da einen Link geben, Jochen.
Kann ich auch an die Schauenfolge.
Das ist ja cool.
Ja, was kann jetzt noch alles dann passieren?
Genau, das ist jetzt sozusagen, der Jochen hat jetzt hier schon die Brücke zu dem zweiten Anwendungsfeier geschlagen, was dann eben hier aus diesem Artikel in der Diskussion rauskam.
Man kann auch im Importsystem was anderes machen.
Und der schöne Vorschlag, der da kam, beziehungsweise das schöne Beispiel, was da in dieser Diskussion kam, ist, dass man ja prinzipiell auch andere Sprachen integrieren könnte.
Einfach Importsystem aufeinandetzen.
Das kann man auch machen, dann ist man in seiner eigenen Welt.
Aber quasi das Gegenteil davon ist, wenn kein Python-Modul gefunden wird, dann kann man mal schauen, ob man irgendwas anderes kompilieren kann, was diesen Namen hat.
Und wenn das kompilierbar ist und kompiliert, dann einfach das importieren.
Und es hat wohl jemand geschrieben, dass jemand sich eben so Lisp-Dateien rein importieren kann, die live kompiliert werden, wenn man sie importiert.
Es ist reichlich abgefahren, würde ich sagen, und ich empfehle auch niemandem, diesen Weg zu gehen.
Aber es ist schön, dass es jemanden gibt, der das gemacht hat und dass es möglich ist.
Ich wüsste jetzt tatsächlich keinen richtig sinnvollen Anwendungszweck davon, aber.
Es gibt irgendeinen, irgendwann wird es einen Anwendungsfall geben.
Ich habe gerade überlegte noch so gut, der mit dem Disp ist jetzt, aber ich meine, jetzt, wenn man das jetzt mit TypeScript macht, man möchte auf dem Backend und dem Frontend den gleichen Code.
Ja, und dann wird es noch mit dem Python, mit dem JavaScript-to-Python-Compiler noch Python gemacht.
Hat man auf dem Server irgendwas, was WebAssembly kann?
Kann Python schreiben für Frontend.
Und schon eigentlich deine Dateien bestehen quasi nur noch aus Import-Stats.
Alles wird mit Import-Statements gemacht.
Ja, das ist so wie der C Präprozessor, der ist auch Turing vollständig.
Ja, tja.
Da hat jemand super wieder sein.
Vorhin haben wir noch drüber gesprochen, ob wir unser
Flugmodus gestellt.
Aber nicht mein Rechner.
Auf meinem Telefon hat es auch nicht geklingelt, sondern aber mein Rechner kann halt auch dummerweise klingeln.
Was kann denn noch alles schief gehen bei den Importen?
Ja, eigentlich
kann beim Importen alles schief gehen, oder?
Das ist ja.
Da steht irgendwas komisches drin, also keine Binärcode oder irgendein anderes Zeichen, das er nicht lesen kann oder sowas.
Es können auch, ich glaube, das Schwierigste an diesem Import-System ist, dass es halt manchmal überraschend ist.
Dass es einem Sachen versucht zu importieren, die man nicht gemeint hat.
Weil die Reihenfolge im Path falsch ist oder weil da Module liegen, die man auch nicht kennt.
Oder weil man versehentlich einen Namen verwendet hat, den es schon gibt.
Also wenn man halt so eine Kette durchgeht, also man möchte jetzt A importieren und A möchte aber ja C, D, E, FG und Y.
Genau, sowas kann
natürlich auch passieren.
Dann hast du zirkuläre Imports, das dann auch schlecht.
Ja, aber das wäre ja von A von B und B von D, B, C und C von A.
Ja, genau, und das hat man ja manchmal.
Aber das war ein anderes Problem, als das ich gerade meinte.
Ich meine, dass da so ganz, ganz, ganz viel Zeugs importiert.
Also du könntest ja quasi eine Sache importieren, der importiert alles andere, die ganze Standardbibliothek.
Ja klar, im Prinzip machst du das ja so, ja, in deinem Skript.
Genau, und das ist halt also relativ getarnt, was da passiert macht, macht relativ viel Magie schon.
Und ja, also was halt die komplizierte Frage wäre, ob das das irgendwie dann doch langsam macht, wenn man irgendwie sowas raussucht und sagt hast, okay, beim ersten Mal schon.
Das heißt, da kann der Starten relativ lange dauern und beim zweiten Mal dann vielleicht nicht.
Aber es gab irgendwie so ein Problem, dass irgendwer hatte, der das mal ausprobiert hat wegen Imports.
Ja, ja, ja.
Also das Problem gibt es halt, wenn du halt irgendwie so auf die Richtung, weiß ich nicht, Millionen Zeilen Python oder so zugehst, dass eben dann, wenn das zum Beispiel im Entwicklungsserver, wenn der neu startet, wenn du änderst halt irgendwas, dann startet er neu und dann dauert das halt eine Minute, dann ist es halt schlecht.
Das ist echt nicht immer so richtig flüssig beim Entwickeln.
Es hieß ja irgendwie so, ne, Google, aber ich glaube, das war bei Instagram das Problem oder so.
Ja, bei Instagram gibt es auch bei Eventbrite gibt es das glaube ich auch.
Ja.
Die sind nicht so groß wie Google.
Ja, aber die haben, glaube ich, auch irgendwie einen, oder verwechsle ich das gerade nicht?
Meines ist Eventbrite, wir haben auch ungefähr eine Million Zeilen-Code und Instagram halt auch.
Vielleicht noch mehr, weiß ich.
Ja, okay.
Aber das ist ja dann so ein, ja, das ist ja dann, das Problem ist ja eigentlich, dass halt die Sachen erst so in Anführungszeichen kompiliert werden, wenn ich Import sage.
Und deshalb haben andere Sprachen das nicht, weil die machen es halt einmal vorher.
Aber so eine richtig gute Lösung, also ich meine, es gibt PyO-Dateien und Pi C-Dateien.
Die sind ja wohl schneller.
Oder könnte man sowas auch marshän?
Könnte man Imports durchführen und das dann.
Ja, im Prinzip schon, oder?
Wahrscheinlich schon, ja.
Einfach mal alles gepickelt.
Tja.
Ach, deswegen auch, weil der Pickel ist die Haube von dem Marshall.
Ah, jetzt verstehe ich das auch.
Ich dachte, Pickel ist so ein Einmachglas.
Marshalls haben doch so eine Pickelhaube auf.
Aber dann passt sie auf jeden Fall zusammen.
Also, also Pickels, sorry, weil ganz.
Das englische Wort Pickels heißt Eingemachtes.
Ja, ja.
Ich glaube, das ist die.
Okay, aber zirkuläre Importe wollte ich nochmal.
Ja, zirkuläre Importe sind auch eine Schöpfung.
Wann passiert das aber?
Also man kann ja sowas machen wie ein Python vom A, Import B und dann ein B machen vom B-Inport irgendwas oder Import A, Import B und D und so.
Und das funktioniert einfach.
Aber erst wenn man es dann ausführt, dann nicht mehr.
Weil er dann darauf zugreift und dann sagt, das kennt er noch nicht.
Weil es unvollständig ist.
Beispielsweise ist schon geladen oder ist schon am Laden.
Ja, genau.
Genau, also wenn ich, wenn ich zirkuläre Verweise habe, ja, vom A Import B und in B sage ich vom A und B habe und in A sage ich Import B und in B sage ich Import A, dann kann ich die beide nicht importieren, weil zu dem Zeitpunkt müsste ich sie beide gleichzeitig importieren und das geht nicht.
Und da kann ich natürlich beliebig viele dazwischen schieben.
Ich kann A, B, C, B, E, solange dieser Kreis sich irgendwann schließt, ist schlecht.
Also es fällt ja direkt auf, aber ich glaube, aber wenn man drei hat, dann fällt es, glaube ich, nicht immer direkt auf, sondern
wenn man vier oder fünf hat, dann fällt es erst recht.
Also da hast du.
Das siehst du dann beim Importieren.
Und wie löst man das denn, wenn man jetzt so ein Problem hat?
Ja, Laufzeitimports.
Also lazy quasi.
Das ist doch das, was man erstmal in so Salary-Tasks immer machen muss.
Weil diese Tasks können von irgendwo her gestartet werden und die sollen dann irgendwas machen.
Und die müssen ja auch irgendwie diese Modelle importieren, aber das Modell selber möchte.
Also das ist so mein klassischer Anwendungsfall.
Ich möchte Modell sagen, ich muss hier Werte nachberechnen, ich muss hier ein PDF erzeugen.
Und das dauert lange und deshalb mache ich das in dem Task.
Aber dieser Task soll ja dann wieder dieses ursprüngliche Modell speichern.
Das heißt, ich kann in der Sellerie, in der Tasks-Datei nicht das Modell importieren, weil das Modell hat schon den Task importiert.
Und deshalb ist das so ein Pattern, ja, wenn man Sellery-Tasks schreibt, dass diese Tasks zur Laufzeit alles importieren.
Also in der Datei, in der Funktion, dev computePDF, habe ich erstmal ein paar Importzeilen drin, Import from Models, Import irgendwas.
Import PDF Generator so.
Und noch alles, was man da halt so importiert braucht.
Und dann werden diese Imports erst ausgeführt, wenn die Funktion gestartet wird.
Also von mir, von meinem geistigen Auge liegen gerade so ein paar Tickets, die noch auf die To-Do-Diste müssen.
Ja, genau.
Das bedeutet halt, dass dieser Import nicht ausgeführt wird, wenn die Datei geladen wird, was eben der Fall wäre, wenn es oben in der Datei drin stinde, sondern dieser Import wird erst ausgeführt, wenn die Funktion, die da drin ist, gestartet wird.
Weil quasi nur der Funktionsname geladen wird und das, was passieren soll, quasi.
Genau, richtig.
Und wenn ich diese Funktion dann ausführe, dann wird dieses Import-Statement ausgeführt.
Und dann sind die anderen Sachen schon da und dann hat man quasi den Laser-Import, dann kann man das dann wieder machen, weil die sind ja schon dann.
Das ist dann schon fertig importiert, diese Models, die sind schon im Cache, dann kann ich einfach in den Cache zeigen und sagen, hey, gib mir das.
Bin also sozusagen aus diesem Prozess raus.
Und das ist auch sowas, was es eben, was eben anders ist als in anderen Sprachen.
Import ist ein Statement, was einen Effekt hat.
In C, wenn ich in C sage, Import Header.h, dann hat es keinen Effekt, das ist kein Code, der da erzeugt wird.
C sonders.
Punkt H ist immer Header, noch ein paar Leute kein C.
Genau, Punkt H ist immer Header, das sind so die Definitionen, was es da gibt.
Die Deklarationen, nicht die Definition, die Deklarationen, was es da gibt.
Und die Punkt C-Datei enthält dann die Definition normalerweise.
Also Header.h ist natürlich dann die Definition der Header.
Die Definition der Header.
Da muss es dann eine Datei dazu geben, die heißt Header.c und die dann halt die, ah irgendwas.
War nur ein Beispiel.
Aber dieses Import-Statement in einem C, das wird vom Compiler ausgeführt.
Das wird nicht zur Laufzeit ausgeführt.
Und in Python ist das anders.
Der Compiler, der macht das, der auch im Ebene, der macht, der schneidet die einfach zusammen, alle zu einer großen Datei und dann liest er einfach von oben nach unten durch.
Und dann gibt es noch
den Linker, der dann dafür sorgt, dass diese Verweise alle an der korrekten Stelle in die korrekte Stelle zeigen.
Das ist so ein mehrstufiger Prozess.
Und es ist halt alles, bevor das Programm gestartet wird.
Und in Python ist immer alles, nachdem das Programm gestartet wird.
Und das ist halt hier genau das Problem.
Wenn ich Import B sage und versuche aber schon was zu importieren oder versuche schon B zu importieren, dann geht es halt nicht.
Weil das gerade, weil das dann eben so einen Kreis bildet, der nicht aufgelöst werden kann.
Wenn ich das aber erst später im Programm sage, wenn ich irgendwelche Funktionen geladen habe, die dann später nochmal diese Module brauchen, dann ist egal, wo die herkommen, wenn die schon im Cache sind, einwandfrei.
Okay, aber das widerspricht ja so ein bisschen dieser Philosophie, das Import immer ganz oben stehen.
Ja, genau.
Deshalb ist das hier so der Nachteil daran.
Ja, ich fühle mich da auch mal so ein bisschen schmutzig, aber ja, ich mache das auch so.
Aber es ist halt
das Pattern und das ist der beste Weg außenrum.
Es gibt noch eine andere Möglichkeit, die ich auch niemandem empfehlen möchte.
Das ist ein sehr schöner Hack, den ich mal gehört habe.
Wenn ich jetzt zum Beispiel nur einen Task importieren möchte, dann sage ich from Tasks Import GradePDF.
Und der Importprozess führt tatsächlich nur so lange diesen Import aus, bis dieses Objekt vorhanden ist.
Alles, was unterhalb dieses Objektes ist, wird nicht ausgeführt.
Das heißt, wenn ich meine Import-Statements ans Ende einer Datei mache, dann kann ich zirkuläre Importe machen.
In bestimmten Situationen, dann geht das.
Aber das auch das, wie gesagt, ist keine Empfehlung.
Es ist nur Imports ans Ende der Datei schreiben, ist schon generell schlecht, weil man sie da nicht mehr sieht.
Und das ist auch dann schlecht, wenn man dann zirkuläre Importe.
Das kann man dann wahrscheinlich auch nochmal so ein bisschen verschachteln oder so.
Also alle Leute, die irgendwie so ein größeres Interesse an Jobsecurity haben, jetzt manchmal aufpassen mit Schreiben.
Das kriegt man hinterher nie wieder auseinander die Frage.
Und wenn man dann noch Homoglyphen nimmt und die Dateien alle gleich ausschauen, dann hat man ganz gewonnen.
Ja, das ist ein Hack, der die interna missbraucht, würde ich nichts empfehlen.
Aber es ist schön, dass es das gibt.
Ja, ist auch manchmal interessant zu wissen, warum irgendwas funktioniert, wo man denkt, das kann ja nicht funktionieren, aber es funktioniert ja dann doch.
Ja, ja.
Nicht so selten, wie es funktioniert, was nicht, was eigentlich funktionieren sollte, aber trotzdem auch.
Ja.
Ja, Imputs haben wir, oder?
Erklärt.
Oder fällt euch noch was ein?
Ich bin mir sicher, dass da noch ganz viele Fragen kommen.
Vor allem, wie funktionieren Imputs in anderen Sprachen?
Ja, anders.
Ich bin mir sicher, dass da ganz, ganz, ganz viele Fragen noch offen sind und dass da ganz, ganz, ganz viele Fragen noch kommen werden.
Aber so, ich glaube.
Also ich meine auch, mir waren da viele Dinge nicht so richtig klar.
Also jetzt nachdem ich den Artikel zumindest teilweise so gelesen habe, dachte ich, ja, okay, da kann man schon coole Sachen mitmachen.
Und vor allen Dingen kann man das auch, dass das eben, dass ein Modul auch nur einfach ein Objekt ist, was irgendwelche Eigenschaften, kann man ja eigentlich total gut ausnutzen, um damit irgendwie Dinge zu machen.
Aber sollte man nicht so ein bisschen.
Sollte man vielleicht nicht, sollte man vielleicht nicht, aber nein, ich meine gerade, also zum Beispiel ein tatsächliches Problem, wo ich halt auch schon so mit Paketen und Dingen rumgespielt habe, wo ich dachte so, oh, da gibt es irgendwie keine gute Lösung für.
Aber es wäre schön, eine zu haben.
Ist halt, oder ich weiß nicht, vielleicht hinzu.
Ich meine, eben im Machine Learning-Bereich, wenn man da Modelle hat, man trainiert die Modelle jetzt aber nicht.
Also man hat normalerweise ein Produktionssystem, was irgendwie dann Dinge tut, so mit echten Usern und echten Daten und so.
Aber da entwickelt man ja nicht und man trainiert ja auch nicht die Modelle, sondern Modelle trainierst du dann meistens irgendwie in einem Jupyter-Notebook oder so.
Und jetzt hast du da dein Modell.
Und jetzt willst du das irgendwie aber in deine Produktionsumgebung integrieren.
Wie machst du das denn?
Jetzt kannst du natürlich jedes Mal, wenn du irgendwie dein Modell trainiert hast, weil das sind ja auch Dinge, die dann auch periodisch passieren und automatisch, kannst du ein neues Paket bauen und das dann releasen.
Aber dieser Deployment-Prozess ist halt ziemlich invasiv.
Also der ist halt, vielleicht willst du das nicht regelmäßig oder auch nicht automatisch machen, weil du brauchst Berechtigungen auf irgendwelchen Systemen und keine Ahnung.
Und dann gut, kannst du das natürlich auch, kannst du irgendwie Deployment automatisieren, was halt so ein bisschen höher ist.
Und du hast dann ganz, ganz viele Paketversionen auch.
Und es ist halt viel, also diese Modelle sind halt teilweise sehr riesig.
Also irgendwie ist das nicht so richtig schön.
Und das ist halt die Frage, wie macht man das eigentlich ordentlich?
Und du hast das Problem, wenn man jetzt Sachen Pickelst zum Beispiel auch, dann ist das von dem Python-Interpreter abhängig und so.
Und der ist möglicherweise in diesem Jupyter Notebook-Umfeld, wo jetzt die Data Scientists irgendwelche trainieren, halt auch wieder anders, aus speziellen Gründen anders als in der Produktionsumgebung, wo dann die Kinder.
Und Pickel kann ja selbst auch Imports durchführen.
Das auch.
Pickel wird ein bisschen aufpassen, wenn man Versionen nimmt oder so, also Sachen pickelt und dann Python-Versionen weitergeht, das geht öfter mal kaputt.
Das heißt, das ist nicht mehr so einfach dann.
Beziehungsweise auch wenn
du andere Imports hast oder andere Versionen.
Pickel importiert halt die Sachen, die es braucht.
Und ja.
Ja, und also das ist, das kann schon, also da gibt es diverse Fallstricke und der Weg, den ich dann da irgendwann gegangen bin, ist halt dynamisch Konda-Pakete zu bauen.
Und weil das mit Konda relativ leicht ging, aber das war, da kann, ich weiß nicht, ob es da Import-Lib, doch, Import-Lib gab es, glaube ich, auch schon, ich wusste aber nicht so viel davon, ich weiß nicht genau.
Und die habe ich dann halt sozusagen als Django-Modelle irgendwie als Files irgendwo hingelegt und dann diese Pakete importiert.
Und dann konnte man einfach einfach sozusagen sich, konnte man in einem Jupyter-Notebook, wenn man fertig Modell fertig trainiert hatte, konnte man sagen, deploy mir dieses Modell irgendwie und dann tauchte das halt auf und wenn man es ausgewählt hat, wurde es halt importiert.
Und zwar einfach aus der Datenbank.
Aus der Datenbank, beziehungsweise nicht aus der Datenbank, sondern aus der Datenbank plus irgendwie, naja, nicht in dem Fallsystem, sondern einer Fallsystemabstraktion, File Storage, Django Storages halt irgendwie.
Und das geht wahrscheinlich auch ohne Konda, nehme ich mal an, so wenn ich das jetzt mir so überlege, was und wahrscheinlich geht das auch noch eleganter, als wie ich das damals gemacht habe.
Ja, aber also jetzt mal die so Diskussionsfrage, ja, warum nicht wirklich aus der Datenbank importieren?
Im Prinzip sind es ja nur irgendwelche Daten, kannst du ja als String da reinlegen und kannst sagen, importiere mir dieses Modell, kannst du einen Re-Import machen und das, also dann wirst du vermutlich noch so ein Proxy-Pattern brauchen.
Ja, also das Ding für Konda war dann halt tatsächlich irgendwie, was ist, wenn ich jetzt irgendeine spezielle Abhängigkeit habe in meinem Modell.
Also ich benutze jetzt irgendeine neue fancy Maschinenlearning-Bibliothek, die ich jetzt auf dem Produktionssystem jetzt aber noch nicht habe.
Ja, okay, dann stellst du es ab und.
Genau, und dann ist halt kaputt.
Wie kriege ich das da mit rein?
Und zwar ohne, dass ich, ja, und das war über Conda ging das, aber.
Ja, okay.
Das ist natürlich schwierig, ja, vor allem, wenn du dann Sachen installieren musst, die der eigentlich, was du an der Stelle eigentlich nicht willst.
Wobei, also ich meine, Pep gibt es auch als Bibliothek.
Da kannst du auch Paper aufrufen.
Von Python heraus.
Also was ich für meine interaktive Programmierensache gemacht habe, ist eben so ein Proxy-Pattern.
Dass du quasi eine Schicht dazwischen hast.
Weil du möchtest ja an der Stelle, wenn du es neu importierst, musst du halt auch ganz viele Instanzen ersetzen.
Eigentlich.
Und das ist schwierig, weil die hast du oft nicht selber in der Hand oder da kommst du oft einfach gar nicht dran.
Also Instanzen ersetzen heißt, du musst die laden mit dem neuen Kontext der neuen Importe erst.
Genau, weil die halt jetzt, weil du einen neuen Code hast und eigentlich müsstest du jetzt die Instanz.
Also du musst aber dann quasi ja alle Transaktionen, die du auf der einen Instanz hast und gemacht hast, schon wieder nachvollziehen, aber du das State ja quasi wiederherstellen musst.
Genau, also genau, das ist die eine Sache, du müsstest den State quasi wiederherstellen und die andere Sache ist, du müsstest den Code ersetzen, weil ich habe jetzt hier halt einen M.x und ich möchte aber ein M.X2 haben.
Aber das State kann jetzt ganz anders sein, weil du hast jetzt nur M.
Ja, genau,
kann sein.
Und dafür gibt es ein Pattern, das heißt Proxy-Pattern.
Wo du quasi ein Interface definierst, was da alles drin ist.
Ich sehe, was das denn ein Interface ist.
Also ja, also.
Also du definierst quasi, was ein Objekt kann.
Also den Typ.
Und die eigentliche Umsetzung ist aber quasi eine Klasse dahinter.
Also du definierst quasi den Typ und dann.
Dieser Proxy macht nichts anderes als diese Aufrufe weitergeben.
Und dann kannst du nämlich dem Proxy sagen, ersetz mal deinen Background, ersetzt mal deinen Hintergrund, den Code, ohne den Proxy selbst anfassen zu müssen, den du halt oft nicht rauskriegst, weil der in irgendwelchen Sachen drin hängt.
Und ich könnte mir durchaus vorstellen, dass das mit so Machine Learning-Modellen auch funktionieren könnte, ja, dass du halt einen Proxy hast, der dieses Modell wegabstrahiert und der kann die Sachen irgendwo her wiederladen, ob das jetzt aus der Datenbank ist oder aus dem Dateisystem oder sonst woher.
Einfach, dass du eine Trennungsschicht drin hast.
Ja, das ist wahrscheinlich auch der richtige Weg.
Das wäre
der richtige Weg.
Ja, man weiß das ja oft zu dem Zeitpunkt nicht so richtig.
Es ist einiges an Verwaltungsaufwand, so ein Proxy richtig zu machen.
Und das geht in manchen Sprachen einfacher.
Ein Interface definieren geht in Java ganz einfach, weil das gibt es da halt.
In Python ist es halt nur eine Klasse, die lauter Not Implemented Arrows hat.
Ja, aber ungefähr so, ja.
Aber achso, gibt es zu diesem Projekt eigentlich auch schon einen Link oder sowas?
Nee, ist demnächst.
Demnächst.
Ich liefere das nach.
Und jetzt habe ich es öffentlich gesagt, jetzt muss ich es auch wirklich machen.
Es ist immer gut.
Sehr schön.
Ich hatte ja, vielleicht rede ich mich ja noch gegenüber mir selbst, kann ich mich immer sehr leicht rausreden, aber wenn ich es jetzt schon gesagt habe.
Ja, gib mal auf jeden Fall deine Bucketlist, dann erwähnen wir es mal öffentlich.
Ja, gut.
Das ist gut.
Ja, also interessant, was man aus so einem Blogartikel noch alles machen kann.
Also wir hatten ja, glaube ich, ja vor, bevor wir einen Block gefunden hatten, irgendwie, und dann war ja irgendwie ergänzende Informationen.
In demselben Blog habe ich noch so ein paar andere Sachen entdeckt, die wir auch vorhaben.
Sowas wie Datentypen sprechen und wie das implementiert ist und wie halt das Python-Objektsystem funktioniert oder die einzelnen Dinge oder der C-Python-Compiler, wie das überhaupt geht.
Und da müssen wir auf jeden Fall auch mal drüber sprechen.
Aber schaut doch schon mal in diesen Blog rein.
10.000 Meters.com, das fand ich wirklich interessant.
Ja, da waren einige gute Sachen aber.
Ja, ziemlich nett
und relativ aktiv aktuell.
Dieses CPyton-Internals Buch besorgt.
Ja, mal schauen, vielleicht kann man da auch noch ein bisschen was rausholen.
Ja, das werden wir auf jeden Fall, also vielleicht verpusten wir tatsächlich so jeden dieser Blogposts.
Also das echt.
Wir lesen die einfach vor.
Nein, das ist wirklich toll und ich glaube, dass viel, was auch Hörer von uns gerne interessiert und wissen wollen, was da irgendwie so passiert, dass man so ein bisschen darüber redet, weil das machen wir ja so ein bisschen erklären wie Python so als Sprache und
so und Wochen.
Ja, auch.
Ja, spannend.
Ja, super.
Ich glaube, wir haben über Impuls gar nicht mehr so viel zu sagen.
Ich habe Gott Johannes hat sich extra einen Pick der Woche überlegt.
Ich habe mir tatsächlich einen Pick und zwar GitHub Octo.
Das ist eine Anwendung, die GitHub geschrieben hat, mit der man Repositories visualisieren kann.
Also die interne Struktur des Codes in einem Repository.
So der Hintergrund ist, du kommst in ein neues Projekt rein und da sind jetzt eine Million Zeilen Pisencode drin.
Und deine erste Aufgabe ist, mach mal hier eine Logausgabe rein.
Es ist sehr schwer, sich da zurechtzufinden und es ist auch sehr schwer, Sachen zu finden in Projekten, wenn man sie nicht sehr genau kennt.
Und da ist eben GitHub Octo, das macht hier so ein paar sehr schöne Graphen, das zeigt quasi grafisch, ich kann es jetzt mal ins Bild halten hier.
Das zeigt quasi grafisch die Abhängigkeiten zwischen den verschiedenen Dateien, wo die liegen und wer sich importiert und wie die, wie die aufeinander aufbauen.
Und dann kann man eben sehr schnell da so einen Überblick bekommen darüber, was mit was interagiert und was wohin gehört.
Also schöne Kreisbeispiele hier.
Wundervoll, das sieht ja richtig kreativ.
Es sieht richtig schön aus.
Komm ausdrucken, die Wand hängen als Kunst jetzt.
Ja, zum einen das und zum anderen auch funktionale Kunst, wo man eben nachsehen kann, von wo man, von wo nach wo man hin navigieren muss.
Und auch interessant, weil es eben so auf eine gewisse Art und Weise die Architektur einer Software widerspiegelt, die ja sehr unterschiedlich sein kann.
Also wenn man sich hier diese Screenshots anschaut, die sind ja zum Teil sehr unterschiedlich.
Manche sind halt sehr flache hier reich.
Die Screenshots werden wir auch insbreit, selbstverständlich.
Sehr gut aufgeteilt, da sieht man vielleicht auch so ein bisschen in Style, das ist ja ganz schön.
Genau, ja, genau.
Also es ist wirklich einfach eine Einsicht, die man sonst nur sehr schwer kriegen kann.
Oder auch hier, also hier gibt es eins.
Das Ding musst du direkt mal in die Gruppe teilen, wirklich.
Wo man eben sieht, dass jedes Paket quasi gleich ist und jedes Paket hat auch so eine Testpunktpile drin und das sind eben halt diese grünen Punkte hier und man sieht, okay, jedes Paket hat eins.
Oder in einem anderen Projekt sind die grünen Punkte halt alle in einem großen Modul drin und man sieht, okay, die sind nebendran, die sind offenbar nicht integriert.
Also es gibt einfach so schnell einen Überblick über die Struktur eines Projektes, was so an sich nicht so einfach zu finden ist.
Okay.
Das ist mein Pick für diese Woche.
Ich habe auch ein Pick.
Ich würde picken OMIGIT.
Das ist ein Spiel, wenn man Git lernen will.
Das habe ich nicht.
Ich weiß gar nicht, in was das geschrieben wurde.
Aber man kann es halt da mit Git spielen, mit so Card und lernen so ein bisschen über Git.
Also natürlich auch so Beginnerlevel und so, aber das ist halt relativ spannend, wenn man so ein bisschen Advanced Git noch machen will.
Also, jetzt ein Rebase, Interactive und dann irgendwie gucken will, dass man irgendwelche Commits-Staht, das dann irgendwie dann doch irgendwie die Message ändern und was man da nicht so alles machen kann, so ein bisschen zu verstehen, was das überhaupt.
Cool.
Hört sich auch spannend an.
Sehr nice, ja.
Also Gamificated, ne?
Gamification mit Git halt als kleines Spielchen, das ist schon irgendwie cool.
Git Efication.
Ja, man sieht halt auch, wenn man es ein bisschen visualisiert und man kann halt so Sachen klicken und das ist irgendwie ganz nett.
Also weil, ne, ich meine, so Branchers oder so, jemand, der so ein bisschen programmiert oder hat das ja irgendwann schon mal gesehen oder viele Leute haben halt dann Git nur zum Pushen oder Pullen verwendet irgendwann.
Man kann echt tolle Sachen mitmachen, also spannende Sachen und ja.
Deswegen kann es interessant, um so ein bisschen Advanced dann noch so schafft zu machen.
Und geht
ja auch in die gleiche Richtung, ist ja spannend.
Ähnliche Picks haben die so.
Ja, ich habe auch was mit Git zu tun.
Lustigerweise.
Ja, auch bei dem Wagtail Media Pull Request ist mir das dann untergekommen, weil ich, ich hatte halt gar nicht gesehen, dass da irgendwelche, normalerweise halt manchmal so Linting-Steps oder so, waren jetzt irgendwie Software testet oder so.
Das war da jetzt gar nicht.
Dann dachte ich mir so schon mal so ein bisschen komisch.
Und dann hat irgendwie beim, gibt es dann auch bei GitHub, hat dann irgendwie das Ding mich angemerkt hat, so dein Code ist ja irgendwie, da sind ja die ganzen Linting-Geschichten nicht richtig und da ist noch was falsch und das ist falsch.
Du warst schon überrascht,
weil du hattest doch alles gemacht, was da drin definiert hat.
Genau, und dann dachte ich schon so, ja gut, so mache ich das halt, das ist doch normal und das ist doch okay.
Und dann dachte ich so, ja, wie passiert das eigentlich, dass GitHub das weiß, dass das nicht okay ist?
Und ja, dann wurde ich mal dann oben auch darauf hingewiesen, so, ja, wir benutzen hier Pre-Comit, benutzen das auch mal auch und dann, und das ist auch ein ganz, das ist, glaube ich, auch noch ein Projekt von Anthony Sotille, oder ich weiß gar nicht, wie man den ausspricht.
Und man definiert das quasi in so einer Art Konfigurationsdatei, was man da gerne hätte.
Und dann sagt man Pre-Commit-Install oder so und dann installiert es alle Abhängigkeiten, die man braucht, um diese Geschichten machen zu können, lokal.
Aber man muss diese Abhängigkeiten dann auch nicht mehr im Projekt haben.
Man hat ja normalerweise auch mal so eine ganze Reihe von Dingen, ja, weiß ich nicht, Black, Flag 8, dieses ganze Zeugs, auch im gleichen Projekt dann immer rumhängen.
Also Dev-Dependencies quasi, Ersatz?
Nee, ist nicht Dev-Dependencies.
Dev-Dependencies sind ja auch nochmal, sind nochmal andere Sachen, aber man hat halt diesen Kram dann da nicht mehr drin, sondern das, ich weiß nicht, ob das ein eigenes Virtual Environment installiert wird.
Ich weiß jetzt gar nicht genau, wie es dann technisch funktioniert.
Auf jeden Fall ist es dann so, wenn man sagt, dann geht commit oder so, dann läuft das dann halt automatisch durch.
Und wenn es nicht richtig war, dann sagt es irgendwie, nee, ich kann nicht committen, weil da ist halt zum Beispiel irgendwie noch ein, da ist ein Flag 8, hat mir gesagt, da ist was faul.
Oder es sortiert ihr halt einfach mal die Imports um mit iSort oder es macht halt irgendwie formatierende.
Man kann seine eigenen Regeln anlegen, also jedes Mal muss man drüber was machen.
Ja, okay.
Genau.
Der Dogswing ist nicht lang genug.
Also das kannst du halt konfigurieren, wie du willst, aber es wird dann halt auch ein Commit gemacht.
So ein Commit gemacht.
Ja, das ist schon auch nicht.
Es ist natürlich auch so ein bisschen hart.
Dockswing länger als eine Zeichen ist ja schon mal super.
Das kann man ja relativ leicht hinfaken.
Ja, genau, aber das fällt ja schon mal auf, wenn er nicht da ist zum Beispiel.
Ja, es ist natürlich relativ hart, aber es ist ja eigentlich schon auch der richtige Zeitpunkt.
Also du kannst nicht
committen, ohne dass alles in Ordnung ist.
Genau, das heißt, es ist damit sichergestellt, dass nicht irgendwelcher Quatsch da drin ist.
Also wahrscheinlich kann man das dann auch noch irgendwie umgehen.
Ist das eine Library oder was?
Nee, das ist auch ein Projekt, das ist auch ein Kommandozeilentool.
Also man benutzt es als Kommandozeilentool und dann sagt im Grunde einmal Pre-Commit install und dann guckt es halt in diese Konfigurationsdateien, macht seine Magie und danach sind diese Git-Hooks gesetzt so weiter.
Und das muss man quasi bei jedem Dev erstmal einmal installieren, damit das funktioniert.
Ja.
Ja, spannend.
Cool.
Ja, finde ich auch gut.
Ja, dann würde ich sagen, sind wir heute durch, auch mit dem Thema.
Und vielen Dank, dass ihr uns wieder zugehört habt.
Und egal wo ihr seid und morgens mittags, abends nachts und bleibt uns gewogen, hört uns gerne wieder, schaltet wieder rein und euch noch einen schönen, was auch immer, Tag, Nacht, wie auch immer.
Bis zum nächsten Mal.
Alles klar, bis zum nächsten Mal.
Tschüss, bis Wochen.