Import einer Instanz einer Klasse in einem anderen Python-File

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
fly2air
User
Beiträge: 7
Registriert: Montag 26. Juli 2010, 08:40

Sonntag 1. November 2020, 18:02

Guten Tag werte Gemeinde,

ich habe folgendes Problem:

Ich habe einen kleinen Service-Container mit einem kleinen Python-Daemon drin. Der soll mir nun, sowie auch aufgerufene importierte Python-Files deren func ich calle, E-Mail senden können. Um nun nicht jedes Mal eine neue Instanz zu erstellen möchte ich diese "durchreichen".
Grund: Ich arbeite mit Multi-Threading und möchte die Verbindung zu meinem eigenen Mail-Server dauerhaft halten und den Bonus an Geschwindigkeit mitnehmen nicht jedesmal einen Handshake machen zu müssen.

daemon.py

Code: Alles auswählen

from my_mail import Mail
from do_something import something
mail_send = Mail(intern_mail_only=True, sender_name="Daemon", mail_from="daemon@bla.de")

something()
Nun möchte ich die Instanz "mail_send" im File "do_something" nutzen.Wie geht sowas?
Wenn ich mail_send im File "do_something" importe, dann habe ich ja einen Cycle, dass funktioniert dann nicht. Wie geht sowas?

Beste Grüße,
fly2air
Sirius3
User
Beiträge: 14594
Registriert: Sonntag 21. Oktober 2012, 17:20

Sonntag 1. November 2020, 18:37

Wie überall gibt, dass man keine globalen Variablen benutzen sollte, sondern die Funktion, die eine Mail senden will, braucht die Instanz von `Mail` als Argument.
fly2air
User
Beiträge: 7
Registriert: Montag 26. Juli 2010, 08:40

Sonntag 1. November 2020, 18:50

Ahhh! Dann reiche ich die Instanz einfach als *kwargs mit durch und dann kann er Mails senden!?

Ich check das mal ^^
fly2air
User
Beiträge: 7
Registriert: Montag 26. Juli 2010, 08:40

Sonntag 1. November 2020, 19:05

Danke Dir Sirius3! Klappt! Sehr gut, ich reiche die Instanz einfach als *kwargs durch und habe mein Ziel erreicht.

Ich möchte auf kwargs verzichten und dies lieber direkt angeben. Daher will ich func annotations nutzen.
Wie kann ich als func annotation das ganze angeben? Ich nutze sonst nur str, int etc. Wie kann ich sagen, dass er meine Mail-Instanz benötigt? 8)
Sirius3
User
Beiträge: 14594
Registriert: Sonntag 21. Oktober 2012, 17:20

Sonntag 1. November 2020, 19:12

Nein! Man reicht nicht irgendwelche Unbekannten Argumente mit **kwargs durch. Das macht das Programm ja noch unverständlicher als globale Variablen. Man benutzt nur konkrete Argumente.
Benutzeravatar
pillmuncher
User
Beiträge: 1266
Registriert: Samstag 21. März 2009, 22:59
Wohnort: München

Sonntag 1. November 2020, 19:18

@fly2air: Kann es sein, dass du Dependency Injection suchst?
In specifications, Murphy's Law supersedes Ohm's.
fly2air
User
Beiträge: 7
Registriert: Montag 26. Juli 2010, 08:40

Sonntag 1. November 2020, 19:33

@Sirius3, siehe letzter Absatz. Ich will auf kwargs verzichten. Nur will ich die func params richtig mit annotations deklarieren.

Wie spezifiziert man denn diesen "Datentyp"?

Code: Alles auswählen

print(type(mail))
<class 'my_mail.Mail'>
Eine classmethod ist es nicht, class, instance gibt es alles nicht. Wie soll ich das als annotation angeben!?

@pillmuncher:

Das kenne ich noch nicht. Danke Dir, ich werde mir es mal anlesen.
Benutzeravatar
__blackjack__
User
Beiträge: 8716
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Sonntag 1. November 2020, 19:34

@fly2air: Wenn Du so wenig über Typannotationen weisst, dann solltest Du sie vielleicht nicht verwenden. Womit prüfst Du die denn? Falls die Antwort „gar nicht“ lauten sollte, dann solltest Du wirklich keine Typannotationen verwenden, denn das weisst Du ja gar nicht ob die auch korrekt sind.
long long ago; /* in a galaxy far far away */
fly2air
User
Beiträge: 7
Registriert: Montag 26. Juli 2010, 08:40

Sonntag 1. November 2020, 19:44

@__blackjack__

Ich nutze die annotation hauptsächlich für meine IDLE. Ich nutze PyCharm und finde es echt super, wenn ich eine func aus einem file lade, dass er mir direkt ansagt, was erwartet wird. Das finde ich sehr nützlich und ich möchte dies nicht nur von Modulen nutzen, sondern auch in meinen eigenen Skripten, wenn ich diese lade und dort eine func aufrufe.

Ich prüfe normalerweise "nur" str, int, dict etc. also die Standardtypen ab. Ich habe noch nie eine Instanz durchgereicht, daher kenne ich diesen Typ leider nicht.

Prüfung: Entweder über if clause mit type oder 'isinstance()'

Code: Alles auswählen

asd = {}
isinstance(asd, dict)
Hast du eine gute Anlaufstelle für Annotations, dann muss ich mich da echt mal weiter einlesen? :wink:
-------------
Edit:
Ich mutmaße mal, es ist ein simples 'object'!?
Benutzeravatar
__blackjack__
User
Beiträge: 8716
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Sonntag 1. November 2020, 19:55

@fly2air: Argh, um Himmels willen NEIN! Du prüfst das bitte nicht mit ``if``, `type()` und `isinstance()`. Die Frage war womit Du die *Typannotationen* prüfst. Ob *die* richtig sind/zum Code passen, und nicht ob die tatsächlich übergebenen Werte den ”richtigen” Typ haben. Wenn Du Python's „duck typing“ nicht magst, dann nimm besser eine andere Programmiersprache, statt das irgendwie manuell nachzubasteln.

`dict` geht auch als Typannonation nicht wirklich vor Python 3.9 und auch da schreibt man nicht einfach nur ``dict`` da hin, sondern einen kompletten Typ der auch Schlüssel und Werte beschreibt. Das aber auch nur wenn es denn tatsächlich ausschliesslich und wirklich ein `dict` sein muss, was es fast nie sein muss.

Ich glaube ich nicht das die meiste Information in PyCharm tatsächlich von Typannotationen kommt. PyCharm wertet dafür nämlich auch Docstrings aus. Wo solche Infos IMHO deutlich besser aufgehoben sind.

Erste Anlaufstelle ist immer die Python-Dokumentation.
long long ago; /* in a galaxy far far away */
fly2air
User
Beiträge: 7
Registriert: Montag 26. Juli 2010, 08:40

Sonntag 1. November 2020, 20:20

@__blackjack__:
Von DuckTyping habe ich eben erst was gehört. Ich kannte vorher, respektive ging vorher immer von 'Dynamic Typing' oder 'Static Typing' aus. ThX für den Hinweis.

So, zu den Annotations:
blackjack, ich weiß doch, was ich in der func "auspacke" oder benötige, demnach setze ich die annotation, schreibe dies in den __doc__ und gut ist. Mit der Frage, wie ich darauf komme, habe ich nicht gerechnet. Ich gehe mal davon aus, dass es eine wichtige Bewandtnis hat, dass Du so direkt danach fragst. Für mich war das immer eher simpel: Ich brauche für einen Adressabgleich, beispielsweise, ein dict(), zwanghaft, denn ich will direkte .keys() haben, damit ich schauen kann nach 'road', 'town', 'street' etc. Daher ist es doch schon wichtig, dass ich das auch direkt deklariere.

Zudem sehe ich es auch als wichtig an, genau zu schauen was mir übergeben wird. Denn wenn ich ein dict() haben will, dann muss ich auch schauen ob der Aufrufer auch alles "korrekt" gemacht hat und mir die Daten auch so gibt wie ich es benötige. Danach bearbeite ich diese und gebe return.
Sollte der Aufrufer etwas nicht korrekt gemacht haben, dann raise/exception.

Habe ich hier einen fundamentalen Denkfehler!?
Sirius3
User
Beiträge: 14594
Registriert: Sonntag 21. Oktober 2012, 17:20

Sonntag 1. November 2020, 20:29

Es ist ein fundamentaler Denkfehler alles kontrollieren zu wollen. Bei Python geht man vom mündigen Programmierer aus. Alles was sich wie ein Wörterbuch verhält, ist ein gültiger Parameter, oder besser, alles was sich wie eine spezialisierte Klasse verhält. Wenn das nicht der Fall ist, wird an einer Stelle schon eine Exception geworfen, ohne dass man das explizit machen muß.
fly2air
User
Beiträge: 7
Registriert: Montag 26. Juli 2010, 08:40

Sonntag 1. November 2020, 20:33

Sirius3 hat geschrieben:
Sonntag 1. November 2020, 20:29
Es ist ein fundamentaler Denkfehler alles kontrollieren zu wollen. Bei Python geht man vom mündigen Programmierer aus. Alles was sich wie ein Wörterbuch verhält, ist ein gültiger Parameter, oder besser, alles was sich wie eine spezialisierte Klasse verhält. Wenn das nicht der Fall ist, wird an einer Stelle schon eine Exception geworfen, ohne dass man das explizit machen muß.
Getreu dem Motto:
James Whitcomb Rileys Gedicht:
"When I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck."
Benutzeravatar
__blackjack__
User
Beiträge: 8716
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Sonntag 1. November 2020, 20:45

@fly2air: Mit den expliziten Tests auf Typen im Code programmierst Du gegen die Sprache. Man kann da auch Objekte übergeben die Schlüssel haben, sich wie ein `dict` verhalten, aber eben *nicht* von diesem Typ abgeleitet sind. Die schliesst Du unnötigerweise aus wenn Du auf den Typ testest und eine Ausnahme auslöst falls es sich nicht um diesen Typ handelt.

Die Annotations sind dazu da auch geprüft zu werden. Wenn Du das nicht tust, dann sind das ja einfach nur Kommentare/Dokumentation. Im Gegensatz zu Kommentaren/Dokumentation sind die Annotationen aber extra dazu da um formal prüfbar zu sein, und Leser erwarten dann auch, dass die tatsächlich stimmen. Bei einem Kommentar kann sich der Autor irren. Annotationen sind immer korrekt, denn der Autor bekommt von der Prüfung ja einen Fehler wenn die nicht zum Code passen.

Bei dem Adressen-Wörterbuch bist Du dann aber wenig konsequent wenn Du einerseits sehr grossen Wert auf ein `dict` legst, aber ob die Schlüssel die zu einer Adresse gehören nicht im Typ beschreibst. Wörterbücher die immer die gleichen Schlüssel haben, sind im Grunde auch keine Wörterbücher sondern Objekte. Also beispielsweise ein `Address`-Typ.
long long ago; /* in a galaxy far far away */
Antworten