Transcript: Das Python Importsystem
Full episode transcript. Timestamps refer to the audio playback.
Ja, hallo liebe Hörerinnen und Hörer. Willkommen beim Python-Podcast in der Episode Nummer 33.
Die hatten wir letztes Mal ausweisend ausgelassen.
Deswegen müssen wir die Episodenummer jetzt ergänzen.
Ja, was machen wir heute? Wir wollen heute über Imports reden.
Hi Jochen.
Ja, hallo. Willkommen Dominik.
Hi Johannes.
Ja, hallo. Ich bin auch mal wieder da.
Ja, wir kennen uns ja alle schon.
Ja, also über das Python-Import-System wollen wir 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 einzigen News, die ich habe, ist, dass Apple sich gerade den größten PR-Unfug aller Zeiten einholt. Aber da ich kein Apple-Gerät habe, geht es so ein kleines bisschen mehr vorbei.
Ja, das Problem habe ich auch nicht.
Jochen, erzähl du doch mal, wie fühlt sich das für dich an?
Ja, nee, tatsächlich ist es PR-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 schlimm.
Was ist denn überhaupt passiert? Vielleicht erstmal so die Story.
War das eine Pressemeldung?
Es war eine Pressemeldung und es war eine technische
Meldung, glaube ich, dass sie jetzt
CSAM angemacht haben,
Content Scanning.
keine Ahnung, was das bedeutet.
Ja, jedenfalls wollen sie,
jedenfalls will Apple jetzt in die Fotos reingucken
und verbotene
Inhalte finden.
Ja, das ist natürlich so ein bisschen,
das, ja. Mit modernster Technologie.
Ja, zum Glück
ist es nicht das
schlimme Technologie, was
man halt auch nehmen könnte, aber
es ist halt irgendwas total Billiges, einfach nur
Hashes in Bildern 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überlaufen lassen und dann Sachen erkennen wollen?
Oder ist das erst der
nächste Schritt? Ja, genau, das ist
halt der Agau-Teil.
Und das ist auch so ein bisschen der Präzedenzfall.
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, also entweder war es ein Unfall,
sozusagen, dass jemand nicht drüber nachgedacht hat,
dass wenn man das so sagt,
dass das dann genau das auslöst bei den Leuten.
Oder es ist 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 PR-Unfall ist.
Aber man weiß es nicht.
Aber es ist ein Präzedenzfall,
dass Apple scannt jetzt Inhalte auf euren Geräten.
Vielleicht ist das die Vorbereitung dafür, dass sie auch in China den Markt
weiter öffnen wollen. 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
man kann sogar... Aber auch da sind viele
Sachen falsch einsortiert. Ja, aber
sie sind da 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 halt, es wird auch nicht an irgendwen geschickt.
Und jetzt ist das natürlich eine andere Sache,
wenn es jetzt eines von den verbotenen Bildern findet,
dann sagt es irgendwie dem Pets, dass das ...
Das sind die leicht verbotenen Bilder?
Ja, wer weiß.
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äsenzfall,
weil das haben sie bisher nicht gemacht, ja.
Na gut, mal sehen, wie sich das entwickelt.
PR-mäßig ist es auf jeden Fall
ein mittleres Desaster. 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!
Also hier auch nochmal der Aufruf von
allen Zuhörern, lasst euch bitte impfen.
Ja, das ist eine gute Idee. Wie viele haben wir jetzt verloren?
Ach, egal.
Die Zuhörer will ich machen. Es gab so einen tollen
Rant-Post von
Linus Torweister, glaube ich auch.
Ja, der sagt auch, lasst euch impfen, ihr Trottel.
Ja, genau.
Ja, Linus Torvalds benutzt noch mehr
ausgewählte Wörter, um das
zu beschreiben, sagen wir es mal so.
Ja, aber inhaltlich doch.
Inhaltlich war es die 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
war sich vielleicht schon länger klar, aber mir war es halt noch nicht
klar, ab Python 3.11
wird
Distutils 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 doch 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 sie sich zum Beispiel
C-Mac 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,
oder so, dass das Ganze zwar kopiert werden muss,
weil meistens ist 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 Tutels.
Und tatsächlich aber auf Mason basierten,
hat hier jemand schon den 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.
Das wäre auch ein sehr positiver
Effekt von dieser Deplication.
Genau. Und ansonsten,
ja, ich glaube, 3.11
ist in der Beta.
3.10 ist in der Beta.
Ich glaube, jetzt um den Dreh
ein Richtkandidat oder was.
Die Zahlen, die gehen so schnell hoch.
Ja, ja. Freuen wir uns schon.
Also ich habe mal den GitHub
Copilot, den wir auch schon mal kurz erwähnt hatten,
ausprobiert. Da habe ich jetzt auch eine Beta-Einladung
bekommen. Ich muss sagen, das ist echt
toll. Also ich habe noch nie so einen
super Effekt von einer KI erlebt.
Ich finde es echt nice. Ich gebe ein,
also ich habe jetzt die VS Code Extension dafür benutzt.
Sowas wie Define and Fibonacci
oder sowas. Und dann
warte ich auf das Autocompletion und dann schreibt
mir die komplette Funktion inklusive Docstrings und Type
Annotations als TypeHint 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,
irgendeine Klasse, Define, Get, bla bla bla.
Und danach fange ich an mit Define.
Und dann schlägt er mir als nächstes vor, Post zu definieren.
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, das ist ein GPT-3.
Ja, also da geht einiges.
Also ich meine, das ist vielleicht auch noch ganz interessant.
Das ist so ein kleiner Abschweif,
aber vielleicht auch nicht so uninteressant.
Ich meine, Text ist ja im Grunde deutlich...
Also dachte man ja immer,
Sprache ist halt schwierig,
aber tatsächlich ist das irgendwie einfacher als andere Probleme.
Und wisst ihr, wie diese Modelle trainiert werden?
Nein.
Das ist halt etwas, was sich allmählich 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 zu haben zu müssen.
Was man ja normalerweise ist immer das Problem bei,
wenn man so überwachte Modelle, also anführungsweise normale Machine Learning Modelle trainiert,
dann braucht man halt Trainingsdaten.
Und damit meint man üblicherweise halt Daten,
wo man Labels
angeschrieben hat, wie zum Beispiel jetzt, wenn man
Bilder hat, so was 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 da zum Beispiel so diese
Newsreuters-Artikel und da 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, Dominik.
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 drauf an, wie gut es sein soll.
Und dann entsprechend
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.
Ne, 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 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.
ja, aber man kann
halt aus Text auch lernen,
ohne diese ganzen Geschichten
haben zu müssen. Also 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
Dinge 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 hat man halt
Feedback, wenn das Modell jetzt ein anderes Wort
als da stand vorher sagt, dann sagt man
okay, das war jetzt falsch und dann kann man
halt irgendwie ein Gradient
bestimmen, in welche Richtung 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 cool.
Man kann das gesamte Internet nehmen und
dann lernt das halt lustigerweise
eben nicht nur irgendwie so
stumpf, welches Wort
die höchste Wahrscheinlichkeit hat, da zu stehen,
sondern um das gut machen zu können,
lernt das halt auch eine ganze Menge Konzepte
und wie Dinge in Verhältnissen stehen und
solche Sachen. 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, genau.
Das ist eine
Geschichte, die man halt auch machen kann, dass man sagt, okay,
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 wenn man sich diese generierten Texte
anguckt, dann ist 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, man kann es halt schnell kaputt machen.
Die meandern auch so ein bisschen, oder?
Wenn man halt so ein bisschen Gedächtnis so ein richtiges...
Kann man es sehr schnell kaputt machen, dann kann es immer 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 eben nicht von einem Menschen geschrieben wurden,
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 Text-Generierung generell, die sind, die werden wohl bestraft, wenn sie Plagiate erzeugen.
Weil das willst du natürlich nicht.
Du willst natürlich nicht ein Paper einreichen, was dann als Plagiate abrechtet.
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 eben kein normaler Mensch
schreiben würde und dann haben sie eben gesucht, wie oft
dieses, 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 Co-Pilot, dass die eben nicht
nur, man muss es dann trotzdem noch für was
Gutes einsetzen und nicht für
Ja, da bist du ja schon
positiv beizuschreiben.
Ja, aber
genau, 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 hat.
Was? Noam Chomsky würde dir widersprechen, Jochen.
Jaja, 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. So größer ist
mein Vocabulary einfach nicht.
Wenn du immer nur ein Wort rausnimmst, ist natürlich klar.
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,
dass das geht.
Es gibt ein bestimmtes Wort wie F,
das fast überall hinpasst.
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
findest, dass das
funktioniert.
Jedenfalls, genau.
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 da drauf trainiert sind, kann man jetzt mit
ganz wenig Trainingsbeispielen auf das
Problem sozusagen,
das man wirklich hat, adaptieren.
Also da braucht man dann nur noch ein paar
Trainingsbeispiele, also nicht mehr viele.
Ich glaube auch, er macht das tatsächlich anhand
des Reposits, was du gerade aufhast.
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
halt bedeutet, dass du im Grunde dieses
Trainingsproblem, Trainingsdatenproblem
los wirst.
Und ja, eine ganze
Menge Anwendungsfälle plötzlich von
ist zu aufwendig, unlösbar,
lohnt sich nicht, in Richtung
kann man schon mal probieren, wandern
und dann ist es natürlich toll.
Also da wird es hier eine Menge interessante
Anwendungen geben. Also gerade für die ganzen
FAUM-Programmierer unter uns, also das ganze Zeug
drumherum, das geht halt einfach jetzt viel automatisierter.
Hatte ich schon gesagt, muss man immer noch selber machen.
Ja, ich bin dagegen, das ist schlecht für die
Auftragsprogrammierer.
Finde ich nicht gut. 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
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 noch dran, 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
sowas, was einem die Forschung
sagt, 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, 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 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.
Naja, keine Ahnung. Ja, aber das zieht
das dann irgendwo aus dem Äther, irgendwelche Formationen
schafft das dann dazwischen und deswegen hast du ja auch so,
weiß nicht, ob ihr das 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 er bestimmte Flecken, die nicht so
ganz klar sind, dann mit Sachen überschreibt.
Einige Leute, die haben dann auch
innere Stimme, die dann auf einmal selbst vervollständigt, die
nur so halb gehört haben. 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 spannend. Wenn die KI das kann, dann kann man quasi
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.
Willst du jetzt zum Topic zurück?
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 irgendjemand eine Idee,
das große ungelöste Problem an der Stelle ist halt,
wenn du jetzt ein Bild aus einem,
ein 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 wären,
nicht aufzählen, nicht so richtig.
Und dann ist es so,
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
hinzu und wie ist der Gradient in welche Richtung?
Aber 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 verschiedene 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 vorhergesagt hat?
Da 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 das,
wie man da die Wahrscheinlichkeit
ausrechnen soll.
Ja, vielleicht braucht man dafür echt einen Kontext,
der das eingesetzt werden soll. Das glaube ich gar nicht so.
Ja, also das ist auf jeden Fall, wenn da jemand eine Idee hat,
voll gut.
Aber 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, das war so ein Syntaxfehler quasi.
Ich sehe schon, es gibt eine gewisse Abschüssigkeit in eine bestimmte Richtung.
Ja, Importsystem ist auch voll interessant.
Na gut.
Ja, Entschuldigung, es war gerade ein Versuch, da so ein bisschen hinzukommen,
weil wir wollten ja über das Importsystem 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 gefeatured worden ist.
Und da hat ein Mensch namens Viktor Skvorstov, wenn ich ihn richtig ausspreche,
einen Artikel geschrieben, wie das
Preis- und Importsystem funktioniert.
Und das hat er so ein bisschen erklärt.
Das ist sehr spannend zu lesen.
Fangen wir auf jeden Fall in die Shownotes.
Und ja, wie funktioniert denn das eigentlich?
Was ist denn das Preis- und Importsystem?
Ja, ich habe diesen Artikel auf Hacker News gesehen
und auch die Diskussion dann so ein bisschen.
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 es da so gibt.
Vielleicht ganz kurz, bevor wir darauf einsteigen,
was ist denn überhaupt das Problem damit? Könnte das sein?
Wir haben irgendwie so eine Story gehört, dass das mal lange dauern kann
und doof sein kann. Worum geht's denn
da überhaupt? Und warum braucht
Python ein Import-System ü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
genauso anfangen wie der Artikel. Was passiert denn,
wenn man sagt Import M?
Warum sagt man das denn überhaupt, Jörg?
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
eine einzige Feier. Also man möchte halt irgendwas
verwenden, was nicht in der aktuellen Datei definiert ist.
Genau. Und jetzt könnte
ich verschiedene Dinge, ich könnte mir
die Datei nehmen und sie e-ballen.
Könnte ich machen.
Ja.
Wäre
auch möglich, oder?
Hat auch einen ähnlichen Effekt irgendwie.
Ja, genau. Aber das
überschreibt dann natürlich manchmal Sachen, wenn ich jetzt irgendwie
zum Beispiel da drin halt,
wenn ich jetzt im aktuellen... Ja, vor allem, wenn man das rekursiv
macht, weil das müsste dann auch immer weiter funktionieren.
Ja, und dann
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 der auch
irgendwie sowas, das macht ja so ein
Namespace wieder. Ja, genau, das müsstest
du dir dann, also wenn du einfach die Datei lädst
und ausführst, also
IWR drauf machst, dann
ja, drü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 in Python auch.
Das Problem haben wir in Python auch, ja, aber
muss man mal überlegen, wie das das macht.
Aber in anderen Sprachen,
um da noch kurz drauf anzugehen,
braucht man es ja, macht man es ja nicht.
In Java oder in C++
macht man es ja nicht, dass man einfach
andere Dateien da reinkopiert,
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 Import-System 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,
das wäre das eine Datei.
Genau, aber wenn du zum Beispiel in C
inkludierst, die ja normalerweise
nur .h-Dateien. Und da sind ja
keine Definitionen
drin. Da sind ja nur Deklarationen drin.
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 es
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,
merkt ihr 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 da Code
drin und so weiter und so fort. Und auch bei
class, 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
Constant-Optimizations
versucht schon mal zu machen, aber generell
wird C-Code
erst ausgeführt, wenn du das Programm startest.
Das ist bei Python
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
Sachen ausführen.
Was
manchmal komisch ist und manchmal gewünscht
und manchmal überraschend.
Ja, also das ist manchmal
tatsächlich, wenn man 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.
Warum passiert
das denn auch? Warum wird das dann ausgeführt? Also wenn man jetzt
ein Import schreibt, Import M
von irgendwo, was dann...
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
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 man könnte auch ein Modul laden,
was halt, wenn ein Modul heißt, das M heißt,
das in einem Verzeichnis ist oder sowas.
Oder was ist ein Modul?
Nee, das wäre dann wieder was anderes.
Ja, aber ein Verzeichnis ist ja auch nur so eine Art Datei.
Ein Verzeichnis ist ja auch nur ein Verweis auf die InitPy.
Also es gibt Module und Packages.
Und was ist denn überhaupt der Unterschied?
Was ist ein Skript, was ein Modul, was ein Package?
Ja, 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 Init-Pi, die da drin ist, dass der Inhalt
dieses Verzeichnisses ist.
Genau, in der Init-Pi
kann man auch sowas wie All dann definieren, das heißt, wenn man zum Beispiel
sowas wie Import-Aspects, das kannst du auch
in einer einzelnen 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. Wenn du all definierst
und dann machst du from m import Stern, dann kriegst du alles das,
was in all drin steht. 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 Stern
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, kannst auch from Stern import Stern probieren, kriegst halt auch 100.000 Sachen rein.
Import Stern habe ich noch gar nicht probiert.
Nee, nee, From Stern, Import Stern geht nicht.
Aber so quasi, wenn du es dir vorstellst.
Import Stern heißt halt, hol alles aus diesem Modul oder aus dem Package
und gib es 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 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 x machst und dann machst du from m import Stern,
hast du auch x importiert, weil das halt in dem Modul m dann schon drin ist.
Und das ist genau der Grund, warum man dieses Stern nicht machen soll,
weil man nämlich nicht weiß, was da drin ist und man halt dann alle Sachen,
die es schon 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 Identität ist.
Aber jetzt müssen wir ja erstmal klären, was Import
überhaupt macht. Wir sprechen jetzt schon die ganze
Zeit über, aber wir wissen es immer noch nicht.
Wir wissen aber immer noch nicht genau, was ein Modul, ein Paket ist.
Ja, also ich glaube, das eine ist eine Datei
und das andere ist ein Verzeichnis.
Ja, aber ich glaube,
es ist auch irgendwie,
ich glaube, der entscheidende
Unterschied ist, dass irgendwie ein Paket Submodule
haben kann und ein Modul nicht.
Also genau,
ich habe eine Definition gefunden bei
der irgendwo sagt hat dann,
if a module name has no dots, it's not
considered to be part of a package.
Aha.
Ja, okay.
Mag sein.
Also ein Paket ist halt quasi eine Sammlung von
Modulen oder sowas.
Okay, gut.
Da gab es auch eine tolle Antwort drin.
Relative imports for the billions times oder sowas.
Ja, relative imports, darüber muss man
auch noch sprechen. Ich bin ein großer Fan davon, aber
offensiv sind die nicht so.
Gut, da kommen wir vielleicht nach.
Ja, ja, ja, okay.
Also was macht denn Import jetzt überhaupt? Import macht,
soll ich mal versuchen, soll ich mal
mein Verständnis erklären und er korrigiert
mich dann. Ja. Von wo importiert
er denn überhaupt? Genau, also Import. Erstmal
sucht Import ein,
also wenn ich sage Import M, dann
sucht das Import-System von Python
nach etwas, das M heißt.
Und zwar. Wo ist das denn? Ja, genau.
Und zwar auf dem Python
Path. Auf dem Path, ah.
Da gibt es eine Variable, die heißt
sys.pythonpath.
Sys.path. Sys.path heißt die, oder?
Okay, ich weiß, ich vergesse es jedes 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,
das ist entweder vorne oder hinten, das ist immer
Ich glaube 0, der erste ist immer
wo du gerade bist. Das ist immer Punkt. Genau.
Also die Datei, wo du gerade aufgeführt bist oder sowas
und dann ist halt quasi, der sucht halt dann im
ersten in eins, wo ab da was drin ist.
Und der erste Hit wird dann genommen.
Genau, der erste Hit wird dann genommen. Und in diesem Path
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 viele Verzeichnisse drin.
Also wenn man verschiedene Pakete haben will, die auch importiert werden können,
dann muss man einfach da gucken. Das ist ein
sys.path quasi in der Umgebungsvariante
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. Genau, das heißt, 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 Path von Python
2 sucht oder so, also wie es
früher offenbar war. Und dann habt ihr 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 Init-Pi hat, oder in Python 3
ein Verzeichnis, was
das M heißt und Python-Dateien
enthält, was keine Init-Pi hat,
dann wird das
als Modul importiert und
in den aktuellen Namespace
als Modul M übergeben.
Wir haben gerade wirklich das schon in Python 2 und 3 diskutiert,
das ist ja interessant. Ja, da gibt es Unterschiede.
Ja, da gibt es auch interessante,
also nochmal ein sehr interessanter Unterschied
kommt mit Python 3.3, glaube ich,
dazu, nämlich die Namespace-Only-Pakete.
Erklär mal.
Die gibt es.
Also früher musste man ja immer die Init-PUI haben.
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
sich dazu bekennt, dass das jetzt ein
Paket sein soll.
Also sozusagen, wenn man sich den Infus
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
Dispass, ja, aber es gibt auch noch irgendwie
andere Stellen, glaube ich. Es gibt auch noch Module,
die nicht da drin sind, zum Beispiel die
Standard-Bibliotheks-Module
sind, also es gibt welche, die sind irgendwie in
das Python-Binary reinkompiliert und dann gibt es
auch noch welche, die sind irgendwie
woanders hingemarschelt, aber die liegen da auch irgendwo
rum. Also die Rang-Python-Module,
die nicht zählen.
Das stimmt, das kann man, aber es gibt
auch noch Dinge, Module, die sind halt einfach nur
in der Shared-Library
und nicht irgendwie Python.
Aber da kommen wir gleich noch so weiter.
Wo der Pycache und so weiter noch was dann kommt, aber egal.
Genau.
Aber man kann halt
auch, es gibt auch Verzeichnisse und denen
wird auch gesucht, wenn da keine NPY 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 ist dann so ein Namespace-Package.
So ein Namespace-Mengeling.
Und dann kannst du halt auch... Also wir erhalten
fest, einfach immer eine Init-Pile.
Ja, dann ist es sicher.
Aber so kannst du halt
auch Dinge in einem Paket haben, die in unterschiedlichen
Verzeichnissen liegen, was halt manchmal auch ganz praktisch ist.
Klar. Man kann das schon brauchen.
Ja, okay.
Okay, also was ist dann
das haben wir gesagt, Package, es gibt auch
ein dann dann Package, was steht
denn da?
Ist das Current Package? Genau.
Ja, das ist das aktuelle Paket.
Das ist ein Top-Level-Modul oder sowas, ja?
Ja, äh,
oh Gott, ich weiß auch nicht, ist es auch so? Ich glaube, also wenn es
None ist, dann ist es ein Skript.
Also vielleicht noch mal zu distinguieren zwischen Skript-Modul
und Pakete oder so, wenn Package None ist,
das ist nur ein Skript und wenn, er sucht halt dann, 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 es.
Passiert mir auch
regelmäßig. Echt, das passiert mir nie, das ist
voll seltsam. Doch, passiert mir auch. 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, wie du gerade gesagt hast.
Ja, die liebe ich. Relative Importe sind voll gut.
Ab und zu 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 from Punkt Import M.
Oder vom dot dot.
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 einen Pfad dran. Ja,
ich glaube tatsächlich, das ist der entscheidende Unterschied.
Ich glaube schon, ja.
Genau, die Top-Level-Package
ist halt irgendwie doch die Sache. Also wenn Package,
wenn man ein Paket finden kann, also ein Top-Level
finden kann, ja, mit diesem Dot-Dot, dann geht das halt.
Aber wenn das None ist, weil man quasi auf der höchsten
Ebene ist, dann gibt es halt Fehler zurück. Und das ist ja genau
der Grund, warum das... Okay, das kann natürlich sein.
Das kann natürlich sein, dass ich das einfach nie... Also für mich
ist einfach Punkt, ja. Wenn ich sage from Punkt
importen, dann weiß ich, das muss im aktuellen Verzeichnis
liegen. Wenn ich sage from 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, also 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 der ja diesen Fehler schmeißen.
Wenn du diese Datei
direkt aufrufst. Genau. Das kann man übrigens
verhindern, indem man einfach sagt, Python minus M
und dann dieses Modul dann
innerhalb von dem Pfad aufrufen. Genau.
Die meisten meiner Projekte sind ja aber in einem Django-Umfeld.
Ja. 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 ist der Pfad, ja,
musst du ja richtig definieren. Ja, aber der
Pfad ist immer festgemacht an der Manage-Pile.
Genau. Das heißt,
das weiß ich. Ich weiß, wo der Pfad...
Ja, aber das ist ja auch Python-M, Package.Module
oder so. Genau. Und deshalb
ist das vielleicht was, was einfach in meiner
täglichen Arbeit nicht so auftritt, dass ich da
mich quasi vernavigiere,
weil meine Projekte
eben immer 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
sind Tests nicht innerhalb von dem Projekt
selber, sondern liegen halt in einem Test-Directory.
Wenn da irgendwas nicht richtig konfiguriert ist, dann passiert
das halt schon mal. Ja, genau, klar.
Und wo es mir halt auch ab und zu passiert ist,
ist halt in Jupyter-Notebooks,
weil die liegen halt auch wieder in einem anderen Verzeichnis.
Und die sind halt auch irgendwo. Genau.
Und deswegen sehe ich das halt
häufiger mal. Bei diesem Importer
auch ganz interessant. Ich glaube, das kommt dann wirklich darauf an, wenn der
Name des Moduls Punkte enthält
oder halt nicht. Weil wenn er
Punkte hat, dann... Ach so, wenn der Name des
Moduls, also wenn das Modul quasi
m.x.y.
Genau, dann ist es halt
ein Part, ein Paket.
So was vermeiden wir jetzt einfach halt noch.
Ja genau, aber nein, andersrum, wenn es halt keinen Punkt
mehr hat, dann muss es eigentlich schon
Top-Level sein, weil dann
kannst du ja nicht.
Ah, okay.
Aber man kann ja jetzt auch so Dinge tun
wie, man sagt
from m import
x oder so.
Habt ihr schon mal Skriptnamen mit Punkten verwendet?
also mit mehreren Punkten drin.
Nee, das ist das, was ich gerade jetzt überlege,
ob ich eine Datei mit Punkten drin hätte,
ohne also Punkt P, Y.
Ich glaube, das kann zu Problemen führen, oder?
Ich glaube auch, dass das zu Problemen führt.
Und das würde ich auch vermeiden einfach.
Ja, interessant.
Stimmt, das habe ich auch noch nicht ausprobiert.
Das müssen wir, das wird dann die nächste Episode.
Was passiert eigentlich, wenn man einen Punkt eingibt?
Ja, genau.
Ach so, genau, die Form import M
ist ja noch vergleichsweise offensichtlich.
Aber jetzt hat der Jochen 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 gibt 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
M-X.py
und die kann ich mit, also an die
komme ich dran, ja, from 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
noch gleich ein bisschen anders. Also man muss
eigentlich immer auf die Datei zeigen, die man
haben möchte. Ja, aber genau, das fand ich auch
Das hat mich auch überrascht, das wusste ich nicht,
wenn man sagt, vom M-Import X,
ich weiß nicht, was ich vorher gedacht habe,
aber ich dachte, das holt das X da raus
und dann hat man das halt im eigenen Namespace.
Aber eben, es macht halt eher sowas wie Import M,
dann sagt es X gleich M.X
und dann sagt es Del M.
Und das ist halt eher so das, was tatsächlich passiert.
Und das ist auch schon so, ui, ui, okay.
Also wenn es nicht geht, macht er doch was anderes,
weil dann holt er sich doch noch die Detail.
Ja, ja, ja.
Achso, und es ist natürlich alles übrigens noch gecached.
Ja, also man kann so oft Import M machen,
möchte es wird nur einmal gelesen die datei und das wird da wo wir das dann reingeschrieben in
das dictionary der offenen der geladenen module das heißt irgendwie punkt das ist auch so eine
eine geschichte das kann man auch schön sehen
verwenden. Also
manchmal braucht man ja, also Singleton,
ein ehrlich gesagt überschätztes
Cooles.
Es hat einen total coolen Namen, deswegen wollen
es die Leute immer verwenden. Aber tatsächlich gibt es
manchmal braucht man das. 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
macht. Und es ist auch manchmal total nervig.
Ja, aber
ich habe da vorher
schon, also meistens habe ich dann Borg-Pattern verwendet
oder halt irgendwas in der Richtung
oder manchmal halt auch, wenn ich nicht Borg
wollte, sondern direkt Singleton, dann wird es aber schon
hakelig, dann kann man das irgendwie, dann muss
man schon so Meta-Klassen 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, ich weiß gar nicht, wo ich das gesehen habe,
den Trick, so dass jemand meinte, ja, ja, Module sind doch
sowieso Singleton, es sind doch einfach globale Variablen
in einem Modul.
Ja, stimmt ja.
Moment, das muss man ja nochmal genau erklären,
warum das ein Singleton ist. Aber Jochen, wenn du dann
wenn du dann das Pattern richtig ausführen musst,
musst du dann noch in dem Modul noch ein Get
irgendwas machen.
Falls das anlegt oder
Falls jemand
versucht darum rumzukommen.
Ja, genau. Eigentlich ja.
Jetzt der Dominik
möchte es gerne erklärt haben.
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 stellt 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 ist.
Und Borg ist, dass es gibt ganz viele
davon, aber die sind alle dieselben Eigenschaften.
Immer.
Ja, da wird der
State geshared, aber es ist nicht
die gleiche Instanz tatsächlich. Es können
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 mir
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 Python halt sagt, ja, die kenne ich ja schon.
Brauche ich nicht nochmal importieren.
Also, weil das Moment, also das,
weil dieser Import, das ist ein, was ist das?
Ein Modultyp dann, wenn du ein Modul hast?
Genau, das heißt Module.
Und dieser Modultyp ist einfach die Zeichenkette,
keine Ahnung, von dem, was ist?
Ja, das Ausgeführte, das ist eigentlich der ausgeführte Code,
der da drin ist, mit so einer Closure, die außen rum.
Weil sonst könntest du keine Daten haben.
Aber das wird dann doch gecastet, was dann Eval wäre?
Oder, das habe ich ja nicht genau klar.
Ja, im Endeffekt macht es ein E-Wahl, 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 musst du ihn irgendwie ausführen.
Irgendwo muss da ein E-Wahl 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.
Er lädt sie einmal.
Aber wenn ich aus mehreren Stellen das habe,
was ist denn dann passiert?
Beim ersten Import Singleton wird diese Datei geladen
und ausgeführt. Ja. Und das
Ergebnis dieser Ausführung wird als Module
Singleton. Ja. Abgelegt
in diesem SysModules Cache.
Und vielleicht wird dann da ein PyCache draus gebracht,
PyC-Files oder so, hat das direkt da?
Ja, nee, das ist nur eine interne
Repräsentation. Das ist halt eben ein internes,
das ist eine Klasse, die heißt Module
und die hat Eigenschaften. Ja.
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 sysmodules.cache und sagt,
ah ja, den Namen singleton kenne ich schon.
Beim ersten Import lädt er das
tatsächlich in den Pycify rein.
Das heißt, er macht aus Bytecode draus,
er komponiert das quasi und er liest das
quasi einmal aus als String und man
macht dann Bytecode draus und dann
schreibt er das in Pycache rein und von da
versucht er dann erstmal zu laden aus Pyc.
Genau.
Und das war jetzt ein Marshall-Objekt?
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 Class machst,
da sind dann so Bytecode-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 ein 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. Okay, und was
wird dann in die PyC-File reingeschrieben?
Die PyC-Files sind so eine
Zwischendurch-Optimierung, weil die
die enthalten
so einen vorkompilierten Bytecode und der
ist schneller zu laden als eine .py-Datei.
Und das ist ein Marschalt-
Object, also wir hatten ganz am Anfang einmal kurz
Marschalt gesagt, was ist das überhaupt? Einmal kurz
nochmal den kleinen Exkurs. Jochen,
erklär du doch mal. Ach ja, damals
genau,
es ist im Grunde Marschaling
ist eigentlich ein anderes Wort,
Oder ist eines der Worte, die man benutzt, wenn man jetzt zum Beispiel Code oder irgendwie eine Datenstruktur serialisieren möchte in eine Liste von Buchstaben oder in einen String oder in eine Byte-Datenstruktur, die man dann halt irgendwie auf einer Platte speichern kann oder 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 immer noch verwenden, kann halt nur relativ wenige Datentypen und in neueren Python-Versionen verwendet man da eigentlich immer Pickle für.
aber das ist halt im Grunde das, was es macht, wenn man
sagt, vom Pickle
oder wenn man sagt
cpickle.dump
oder so, dann wird das halt in String oder Dump
in einen Teil geschrieben und dann hat man halt
eine in einem String serialisierte Form von
zum Beispiel irgendwie Code.
Also mittlerweile nimmt, glaube ich, sogar Dill oder sowas,
dass man irgendwie import Dill as Pickle
oder so, also neue Version.
Als Third-Party-Package irgendwie.
Schön.
Okay, aber ein Marschalt-Objekt, falls ihr das irgendwo findet,
ist quasi eine serialisierte
Form von dem
Speisen-Code, der da gelaufen ist.
Genau.
Okay, jetzt haben wir es irgendwo geladen,
haben wir es gefunden. Was importiert ihr dann? Was ruft ihr dann auf?
Ja, das Ergebnis
dieser Ausführung.
Also import.dott, dann dann import.
Dann dann
crawl. In diese Funktion
kommen dann halt die Argumente rein, die
Ja, nee, das kann ja alles möglich sein.
Du kannst ja auch beliebige Objekte in der Datei
reinschreiben. Du kannst auch ein Modul machen,
was einfach nur einen String enthält, wo irgendwelche
Binärdaten drin sind.
Macht man ja manchmal, weil man Testdaten
braucht.
Das Modul hast, wo einfach so ein paar Strings
drin sind. Und wenn die eben ausgeführt werden,
dann werden die halt so ein
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, Dikt,
Unterstrich, Unterstrich. Das hat natürlich noch
mehr so Attribute.
Der Path ist da drin und
der ursprüngliche Importname
und der Dockstring wird rausgelesen
und so weiter. Also diese ganzen Sachen, die halt
so passieren, wenn Python was ausführt,
die passieren da auch.
Alles, was Python langsam macht.
Alles, was Python awesome macht.
Ja.
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.tikt und Modul.
Was weiß ich nicht noch alles. .name und .path
und .package.
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, die müssen ja erzeugt werden und wenn es so Meta-Klassen hat, dann müssen die ausgeführt werden. Also alles das, was da, ja, 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 man das braucht, dass ich halt einfach bestimmte Python-Objekte oder bestimmte Dinge in andere Dateien reinschreiben möchte.
Und diese Dateien sollen in anderen Verzeichnissen liegen, damit ich nicht die Übersicht verliere.
Und ja, so, das ist Import.
Und jetzt gibt es noch Importlib.
Ja, das wird ja aufgerufen sogar, also Import wird ja bei 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, ganz weit unten.
Es gibt Importlib 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 diese Statement Import M ist quasi nur noch ein syntaktischer Zucker für Importlib Punkt, keine Ahnung, 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
Dinge verweisen, da werde ich
in Kürze ein Video dazu hochladen.
Kommt dann natürlich in die Show noch.
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.
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 Importlib. 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.
Ja, cool.
Ja, ich meine, der Entwicklungs-Server von Django,
der kann sowas ja auch.
Ja, aber der macht ja einen Neustart.
Der macht tatsächlich einen Neustart, na ja.
Der hat so einen Watcher-Prozess
und dann schießt er einfach den Prozess ab
und startet einmal neu.
Ach so, 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.
Ja, ja, das, ja.
Wie ist das denn bei Jupyter?
Ist das ja auch so.
da kann ich ja auch beim Import sagen,
ob ich das jetzt möchte, dass ich das nochmal
importieren will, wenn es sich ändert.
Ja, dann mach so ein Reimport.
Da gibt es eben diese Jupyter-Magic,
die du sagen kannst und der benutzt tatsächlich
Import-Lib und macht Reimport.
Aha, okay.
Neu starten wäre auch blöd.
Ja, 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, ne, letzte oder vorletzte, ne,
letzte Woche, und ich erinnere mich schon nicht mehr dran,
den Fall, wo ich tatsächlich Importlib
gebraucht habe und habe halt die Importfunktion
überschrieben.
Was hast du damit gemacht?
Ich habe einen Pull-Request
bei Wagtail Media
eingereicht, weil es nicht mit
Wagtail 2.13 kompatibel war.
Spannend.
Ja, da gibt es Tests
und das Problem ist jetzt,
dass man jetzt in den, 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 Backtail
2013. Okay.
Und da sagt man halt, probier es zu importieren.
Ja, auch für lokale, ich benutze es ganz häufig für lokale
Settings, ja. Irgendwo eine local settings
.py und dann macht man halt
Try-Import-Local-Settings-to-Py
und Accept-Parse.
Genau, genau.
Und jetzt möchten wir das aber testen.
Jetzt möchten wir testen, dass wenn
und es gibt da noch komplizierter
wie gesagt, das habe ich jetzt wieder vergessen, blöderweise, ein bisschen komplizierter
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, der 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.
Ja, und dann habe ich da
einfach quasi Importfunktionen
überschrieben und dann in der Importfunktion gucke ich halt so,
wird gerade versucht, das da zu importieren?
Ja, wirklich? Gut.
Race Exception, 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...
Das ist ja spannend, aber das ist auch ganz schön tief
eingegriffen in die...
Hat der Jochen auch schon aufgenommen?
Ja, genau.
Du musst jetzt aber suchen, in welcher Folge das war.
Kannst du uns da einen Link geben, Jochen?
Kann ich auch mal in die Schauenden folgen.
Das ist ja cool.
Ja, aber es kann ja noch alles dann passieren.
Genau, das ist jetzt sozusagen,
der Jochen hat jetzt hier schon die Brücke
zu dem zweiten Anwendungsfall 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
aufeinandersetzen. 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 ja mal schauen, ob man
irgendwas anderes kompilieren kann, was diesen Namen hat.
Und
wenn das kompilierbar ist und kompiliert, dann
einfach das importieren.
Und das hat wohl jemand geschrieben, dass jemand sich eben
so Lisp-Dateien rein importieren kann,
die live kompiliert werden,
wenn man sie importiert.
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
naja,
irgendwann wird es
einen Anwendungsfall geben.
Ich habe gerade überlegt,
wenn man das jetzt mit
TypeScript macht,
man möchte auf dem Backend und vorne den gleichen
Code. Ja, und dann
wird es noch mit dem
JavaScript-to-Python-Compiler
zu Python gemacht. Dann hat man noch
einen Server, irgendwas, was WebAssembly kann.
Man kann Python
schreiben für Frontend. Und schon
eigentlich, deine Dateien
bestehen quasi nur noch aus Import-Statements.
Alles wird mit
Import-Statements gemacht.
Ja, das ist so wie der 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
Telefon ausfalten wollen.
Flugmodus gestellt, aber nicht
mein Rechner.
Auf meinem Telefon hat es auch nicht geklingelt, sondern
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...
Ja. Da steht irgendwas Komisches
drin, also keine Binärcodes oder irgendein andere
Zeichen, das er nicht lesen kann oder sowas.
Ja, es können auch...
Ich glaube, das Schwierigste an diesem Importsystem
ist, dass es halt manchmal überraschend ist, ja, 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
so eine Kette durchgeht, also man möchte jetzt A importieren
und A möchte aber ja C, D, E,
F, G und Y. Genau, sowas kann natürlich auch passieren,
dann hast du zirkuläre Imports, das ist auch
schlecht. Ja, aber das wäre ja von A
von B und C und C von A.
Ja, genau, und das hat man ja manchmal.
Aber das war ein anderes Problem, als das, was ich gerade meinte.
Ich meine, dass da so ganz, ganz, ganz viel Zeugs importiert ist.
Also du könntest ja quasi eine Sache importieren,
und der importiert alles andere, die ganze Standardbibliothek.
Ja, klar. Im Prinzip machst du das ja so in deinem Skript.
Genau, und das ist halt so relativ getarnt, was da passiert.
Man 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,
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,
das irgendwer hatte, der das mal ausprobiert hat
wegen den Imports.
Ja, ja, ja. Also das Problem gibt es,
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 so änderst irgendwas, dann startet der neu.
Und dann dauert das halt eine Minute.
Das ist halt schlecht. Das ist immer so richtig flüssig
beim Entwickeln.
Es hieß ja irgendwie so, wie an 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.
Die sind nicht so groß wie Google.
Ja, aber die haben, glaube ich, auch irgendwie
oder
verwechsel ich das gerade? Nein, ich meine, es ist Eventbrite.
Die haben auch ungefähr eine Million Zeilen Code und Instagram
halt auch, vielleicht noch mehr, weiß nicht.
Ja, okay.
Aber das ist ja dann so,
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 das halt einmal vorher.
Ja.
Aber so eine richtig gute Lösung, also ich meine, es gibt
PyO-Dateien und PyC-Dateien,
die sind ja wohl schneller.
Ja.
Oder könnte man
sowas auch marscheln?
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 Marschall.
Ah, jetzt verstehe ich das auch.
Ich dachte, Pickel ist so ein Einmachglas.
Die Marschalls haben doch so eine Pickelhaube auf.
Ja. Also dann passt
es auf jeden Fall zusammen.
Sorry, weigert mich.
Das englische Wort Pickles 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öne Sache. Also man kann ja sowas machen wie
in Python Form A Import B und dann
in B machen Form B Importe irgendwas
oder Import A, Import B, Import 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.
Es ist schon geladen oder es ist schon am Laden.
Ja, genau. Also wenn ich
zirkuläre
Verweise habe, ja, vom A Import B
und in B sage ich vom
wenn ich Modul 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, D, E, S.
Solange dieser Kreis sich irgendwann schließt,
ist schlecht.
Also es fällt ja direkt auf. Ich glaube, wenn man
drei hat, dann fällt es glaube ich nicht immer direkt auf.
Wenn man vier oder fünf hat, dann fällt es erst
recht. Also das siehst du
dann beim Importieren. Und wie löst man das denn,
wenn man erst so ein Problem hat? Ja,
Laufzeitimport.
Also lazy quasi. Ja.
Das ist doch das, was man in
so Salary-Tasks immer machen muss.
Weil diese Tasks können von irgendwoher
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
Tasks-Datei nicht das Modell
importieren, weil das Modell hat schon den Task
importiert. Und deshalb
ist das so ein Pattern, wenn man
Celery-Tasks schreibt, dass diese
Tasks zur Laufzeit alles
importieren. Also in der Datei,
in der Funktion
dev-compute-pdf
habe ich erst mal ein paar Importzeilen drin,
Import from Models, Import irgendwas.
Import PDF Generator.
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, die haben gerade so ein paar
Tickets, die noch auf die To-Do-Liste 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 drinstehende. Sondern dieser Import
wird erst ausgeführt, wenn die Funktion,
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, importiere diese Models,
die sind schon im Cache, dann kann ich einfach in den Cache zeigen
und sagen, hier, 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. Also C.h ist immer
Header, noch mal für alle Leute kein C.
Genau, .h ist immer Header, das sind so die
Definitionen, was es da, die
Deklarationen, nicht die Definitionen, die Deklarationen,
was es da gibt und die .c-Datei
enthält dann die Definitionen
normalerweise.
Also header.h ist natürlich dann die Definition der Header.
Die Definition, da müsste es dann
eine Datei
dazugeben, die heißt header.c
und die dann halt,
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 schneidet die einfach zusammen,
alle zu einer großen Datei und dann liest der 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, an 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 es
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, ist egal, wo die herkommen,
wenn die schon im Cache sind, einwandfrei.
Okay, aber das widerspricht ja so ein bisschen dieser
Philosophie, dass Importe immer ganz oben stehen.
Ja, genau. Deshalb ist das hier so der
Nachteil da dran.
Ja, ich fühle mich da auch immer 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. Es 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,
Great PDF.
Und der Import-Prozess 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 auch das, wie gesagt, ist keine Empfehlung.
Es ist nur, Imports ans Ende der Datei schreiben
ist schon generell schlecht, weil man sie dann nicht mehr sieht.
Und es ist auch dann schlecht, wenn man dann zirkuläre Importe ...
Das kann man dann wahrscheinlich auch noch ein bisschen verschachteln.
Also alle Leute, die ein größeres Interesse an Job Security haben,
jetzt bitte mal aufpassen mit Schreiben.
Das kriegt man hinterher nie wieder auseinander.
Ja, nee.
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 nicht 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 gar 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, Imports haben wir, oder?
Erklärt, oder fällt euch noch was ein?
Bin mir sicher, dass da noch ganz viele Fragen kommen.
Vor allem, wie funktionieren Imports in anderen Sprachen?
Ja, andersrum.
Das ist nicht so genau.
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.
Einfach mal so ein bisschen als Einstieg,
weil ich meine auch, mir waren da viele Dinge nicht so richtig klar.
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,
das ist irgendwie die Eigenschaft, kann man ja eigentlich
total gut ausnutzen, um damit irgendwie
Dinge zu machen.
Aber sollte man. 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's
irgendwie, gibt's da keine gute Lösung für,
Aber es wäre schön, eine zu haben.
Oder ich weiß nicht, vielleicht kennst du eine.
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.
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 ja natürlich jedes Mal, wenn du
irgendwie dein Modell trainiert hast, aber das sind ja oft 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.
Vielleicht willst du das nicht regelmäßig
oder auch nicht automatisch machen, weil
du brauchst ja Berechtigungen auf irgendwelchen Systemen und
keine Ahnung. Gut, kannst du das natürlich auch
Deployment automatisieren, was halt so ein bisschen
höhe ist. Und
du hast dann ganz, ganz viele Paketversionen
auch. Und es ist halt viel,
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
pickelt 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 Modelle trainieren,
halt auch wieder anders, aus speziellen
Gründen anders als in
Produktionsumgebungen, wo dann die
Und Pickel kann ja selbst auch Imports
durchführen. Ja.
Das ist auch... Pickel muss man 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... Ja, 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 irgendwann gegangen bin, ist halt dynamisch
Conda-Pakete zu bauen
und weil das mit Conda relativ leicht ging,
aber das war, da kann, ich weiß nicht, ob es da
Importlib, doch, Importlib 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-Notepunkt, wenn man ein 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
Aus der Datenbank importiert.
Aus der Datenbank, beziehungsweise nicht aus der Datenbank,
sondern aus der Datenbank plus irgendwie,
naja, nicht in dem File-System, sondern
in der File-System-Abstraktion,
dem File-Storage,
Django-Storage ist halt irgendwie.
Und das geht
wahrscheinlich auch ohne Conda, nehme ich mal an,
so, wenn ich das jetzt mir so überlege,
und wahrscheinlich geht das auch noch
eleganter, als wie ich das damals gemacht habe.
Ja, aber also jetzt mal
die
Diskussionsfrage, 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 ein Reimport machen und das
also, dann wirst du vermutlich noch so
einen Proxy-Pattern brauchen.
Ja, also das Ding für Conda
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 Maschine in der Bibliothek,
die ich jetzt auf dem Produktionssystem
jetzt aber noch nicht habe. Ja, okay, dann
stößt das 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 du eigentlich, was du an der Stelle
eigentlich nicht willst. Wobei, also
ich meine, PIP gibt es auch als Bibliothek, da kannst du
auch PIP aufrufen,
von Python heraus.
Also,
was ich für meine
interaktive
Programmieren-Sache 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, das heißt, du musst die laden mit dem
neuen Kontext der neuen Importe. Genau.
Weil du den neuen Code hast und
eigentlich müsstest du jetzt die Instanzen...
Du musst aber quasi ja alle Transaktionen, die du auf der einen Instanz
hast du gemacht, hast du wieder nachvollziehen, weil du den State
ja quasi wiederherstellen musstest. 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 ein m.x
und ich möchte aber ein m.x2 haben.
Aber der State kann jetzt ganz anders sein, weil du hast jetzt nur m.
Ja, genau, kann sein. Und dafür gibt es
einen Pattern, das heißt Proxy-Pattern,
wo du quasi ein Interface definierst,
was da alles drin ist.
Was ist denn ein Interface? Also ja, also
du definierst quasi,
was ein Objekt kann. Also ein Typ.
Und die eigentliche Umsetzung
ist aber quasi eine Klasse dahinter.
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,
ersetz 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.
Ich könnte mir durchaus vorstellen, dass das
mit so Machine Learning Modellen auch funktionieren
könnte, dass du halt einen Proxy hast,
der dieses Modell weg abstrahiert und der
kann die Sachen irgendwoher 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 gut,
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 es
gibt es da halt. In Python ist es halt
nur eine Klasse, die lauter Not-Implemented-Errors
hat.
Ja, aber ungefähr so, ja.
Ja.
Achso, gibt es zu diesem Projekt
eigentlich auch schon einen Link
oder sowas? Nee, demnächst.
Wird nachgereicht.
Ich liefere das nach. Okay.
Und jetzt habe ich es öffentlich gesagt, jetzt muss ich es auch wirklich machen.
Das ist immer gut. Sehr schön.
Ich hatte ja, vielleicht rede ich mich ja
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 vorher, bevor wir einen Blog
gefunden hatten, irgendwie, und dann war ja irgendwie
ergänzte Information. 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-Objekt-System
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
Bock rein, 10.000 Meters, komm, das fand ich wirklich interessant.
Ja, da waren einige gute Sachen dabei.
Ja, ziemlich nett und relativ aktuell.
Ja, ich hab mir auch mal dieses
Sea Python Internals Buch
besorgt.
Ja,
mal schauen,
vielleicht kann man da ja auch noch ein bisschen was rausholen.
Ja, das werden wir auf jeden Fall, also vielleicht verpusten wir tatsächlich so
jeden dieser Bock-Posts, also
wir lesen die einfach vor.
Wir lesen die einfach vor.
Nein, das ist wirklich toll und ich glaube, das ist viel, was
auch Hörer von uns gerne interessiert und wissen wollen,
was da irgendwie so passiert, dass man so ein bisschen drüber redet, weil
das machen wir ja, so ein bisschen erklären, wie Python
so als Sprache und
so und warum.
Ja, spannend.
Ja, super. Ich glaube, wir haben
über Impulse gar nicht mehr so viel zu sagen.
Ich habe gehört, Johannes hat sich extra einen Pick der Woche überlegt.
Ich habe mir tatsächlich,
ich habe 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.
Der Hintergrund ist,
du kommst in ein neues Projekt rein und
da sind jetzt eine Million Zeilen
Python-Code drin und deine erste
Aufgabe ist, mach mal hier eine
Log-Ausgabe 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 Grafen,
das zeigt quasi grafisch,
ich kann es jetzt mal ins Bild halten hier,
zeigt quasi grafisch
die Abhängigkeiten zwischen den verschiedenen
Dateien, wo die liegen und
wer sich importiert und 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 aus.
Es sieht richtig schön aus.
Zum Ausdruck an die Wand hängen, also als Kunst jetzt.
Ja, zum einen das und zum anderen auch funktionale
Kunst, wo man eben nachsehen kann,
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 Hierarchien.
Die Screenshots werden wir auch nicken.
Sehr breit, selbstverständlich.
Das sind sehr gut aufgeteilt, das sieht man vielleicht auch so ein bisschen
in Style, das ist ja ganz schön. Genau, genau, also
es ist wirklich einfach eine Einsicht, die man
sonst nur sehr schwer kriegen kann
oder auch hier, also hier gibt es eins.
Den musst du direkt mal in die Gruppe teilen. Ja, selbstverständlich.
Wo man eben sieht, dass jedes Paket quasi
gleich ist und jedes Paket hat auch so eine Testpunkt-Pi
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 sehr schnell einen Überblick über die
Struktur eines Projektes, was so
an sich nicht so einfach
zu finden ist.
Das ist mein Pick für diese Woche.
Ich habe auch einen Pick. Ich würde picken
Oh My Git.
Das ist ein Spiel, wenn man Git lernen will.
Oh My Git? Ja, Oh My Git.
Ich weiß gar nicht, in was das geschrieben wurde.
Aber man kann es halt
mit Git spielen, mit so Karten und lernt so ein bisschen
über Git. Also natürlich auch so Beginner-Level und so,
aber das ist halt relativ spannend, wenn man so ein bisschen
Advanced-Git noch machen will.
also, weiß nicht, jetzt ein Rebase, Interactive
und dann irgendwie gucken will, dass man irgendwelche Commits
stasht, dass 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
ist. Cool, hört sich auch spannend an.
Sehr nice, ja, also Gamification
mit Git halt als kleines Spielchen,
das ist schon irgendwie cool. Gitification.
Ja, man sieht halt auch, wenn man das ein bisschen
visualisiert und man kann da so Sachen klicken und das ist
irgendwie ganz nett, also weil, ich meine, so Branches 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, dass man so ein bisschen, man kann echt
tolle Sachen mitmachen, also spannende Sachen und
ja, deswegen kann ich es
interessant, um so ein bisschen Advanced dann noch zu machen.
Und geht ja auch in die gleiche Richtung, ist ja spannend.
Ja. Ähnliche Picks haben die so.
Ja, ich habe,
hat auch was mit Git zu tun.
Lustigerweise.
Ja, auch bei dem
Backtail-Media-Pool-Request ist mir
das dann untergekommen,
weil ich
hatte halt gar nicht gesehen, dass da
irgendwelche
normalerweise hat man
immer so Linting-Steps oder so, wo man
jetzt irgendwie Software testet
oder so, das war da jetzt gar nicht.
Da dachte ich mir, das ist schon mal ein bisschen komisch.
Und dann hat irgendwie beim,
bei GitHub hat dann irgendwie
das Ding mich angemerkt, so, dein Code ist ja
irgendwie, da sind ja die ganzen Linting-Geschichten nicht richtig
und da ist noch was falsch und es ist falsch,
du warst schon überrascht, weil du hattest doch
Macht, was da drin definiert war. Genau, und ich dachte 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 aber dann auch darauf hingewiesen, so
ja, wir benutzen hier
Precommit, benutzen das auch mal
auch. Und dann,
und das ist auch ein ganz, das ist glaube ich auch noch ein Projekt von
Anthony Soti, 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
Precommit install oder so und dann
installiert es alle Abhängigkeiten, die man braucht,
um diese Geschichten machen zu können lokal.
Aber man muss die halt, diese Abhängigkeiten
dann auch nicht mehr im Projekt haben. Man hat ja normalerweise
auch mal so eine ganze Reihe von Dingen,
ja, was weiß ich nicht, Black, Flag 8,
dieses ganze Zeugs, auch im
gleichen Projekt dann immer rumhängen und
Es ist Death Dependencies quasi, Ersatz, oder?
Ne, es ist nicht
Death Dependencies. Death Dependencies sind ja auch nochmal
andere Sachen, aber man hat halt diesen Kram
dann da nicht mehr drin, sondern das, ich weiß gar nicht,
dass 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 git commit oder so, dann läuft
das dann halt automatisch durch
und wenn es nicht
richtig war, dann
sagt es irgendwie, nee, kann nicht committen, weil da ist
halt zum Beispiel irgendwie noch ein
Flag 8 hat mir gesagt,
da ist was faul oder es sortiert hier halt
einfach mal die Imports um mit iSort oder es macht halt
irgendwie formatierende Code. Man kann seine eigenen Regeln anlegen,
also jedes Mal muss man über drüber was machen.
Ja, okay. Genau. Der Dock Swing ist nicht lang genug.
Ja,
also das kannst du halt konfigurieren, wie du willst,
aber es wird dann halt automatisch beim Commit gemacht.
Ja, das ist schon auch der richtige Zeitpunkt.
Das ist natürlich auch so ein bisschen hart.
Ja, klar.
Doch, es klingt länger als eine Zeiche.
Das 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 ...
Also wahrscheinlich kann man das dann auch noch irgendwie umgehen.
Ist das eine Library oder was?
Ja, das ist ein Projekt, das ist auch ein Kommandozeilentool.
Also man benutzt
das als Kommandozeilentool und dann sagt man im Grunde einmal
pre-commit install und dann guckt es halt
in diese Konfigurationsdateien, macht seine
Magie und danach sind diese Git
Hooks gesetzt. Aber das muss man quasi
bei jedem Dev erstmal einmal installieren, damit das funktioniert.
Ja, okay. Genau.
Ja, spannend.
Ja, fand ich auch gut.
Ja, dann würde ich sagen, sind wir heute durch
auch mit dem Thema und vielen Dank, dass ihr uns wieder dazugehö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 demnächst.
Alles klar, bis demnächst mal. Tschüss.