An die python cracks. Hilfe bei Minidisplay.

  • @tjost

    Dein Code ist schon eine Herausforderung ;)

    zu Problem 2.
    füge

    toggled_text = ''

    vor dem while True: ein und innerhalb z.B.

    elif window=="10502":

    machst Du dann

    toggled_text = "WOAS IS?" if toggled_text == "Music" else "Music"

    und anstelle von "Music" gibst Du bei draw.text dann die Variable toggled_text an.


    Damit würde mit jedem Durchlauf zwischen Music und WOAS IS? gewechselt.


    Generell würde ich Dir empfehlen eine Funktion zu definieren, welche das aktuelle Bild erstellt und anzeigt.

    Etwa wie


    Python
    def create_and_display_image(top_text='test', bottom_text='test', top_font=font36, bottom_font=font28):
            draw.rectangle((0,0,width,height), outline=0, fill=0)
            w,h = draw.textsize(top_text, font=top_font)
            mid = (width-w)/2
            draw.text((mid, top), top_text, font=top_font, fill=255)
            w,h = draw.textsize(bottom_text, font=bottom_font)
            mid = (width-w)/2
            draw.text((mid, padding), bottom_text, font=bottom_font, fill=255)
            disp.image(image)


    aufgerufen ohne Parameter werden die Standardwerte genommen. Ansonsten die die übergeben werden also in etwa

    Python
    if PlayerisMovies==True:
        create_and_display_image(systemtime, videotime)

    oder

    Python
    elif PlayerisEpisodes==True:
        create_and_display_image("S:{} /E:{}".format(season, episode), videotime)

    oder

    Python
    elif window=="10016":
        create_and_display_image("System", "Settings", font32)


    Wenn Du aber den top_font nicht übergeben willst, den bottom_font aber schon mußt du diesen benennen also

    create_and_display_image("System", "Settings", bottom_font=font32)

    damit python auch richtig zuordnen kann, sprich weiß, dass der übergebene dritte Parameter eigentlich der vierte ist.

    Damit wären 90% deines redundanten Codes nicht mehr nötig.

    Zu Problem 1,
    ich habe mal in die Python Bibliothek von Adafruit geschaut und es sieht nicht aus als ob es eine interne Routine gibt, welche das
    ein- und auslaufen eines Textes bewirkt. Das heisst Du hast aus meiner Sicht folgende Möglichkeiten.

    1) Du könntest einen Thread erstellen, der diese Animation auf Anforderung erfüllt, nicht ganz trivial
    2) Du könntest innerhalb deines while loops einen weiteren loop bauen der die Animation macht, durch den Timeout würde das aber wahrscheinlich unschön
    3) Du überdenkst dein Konzept und versuchst das geforderte über Callbacks zu lösen (in wie weit alles über den Mechanismus zu lösen ist, vermag ich nicht zu sagen, hab ich nicht recherchiert.)

    Deinen while True würde ich gegen einen waitForAbort tauschen, damit Kodi auch die Möglichkeit hat sauber zu stoppen.
    Die pass statements sind überflüssig wenn Du Code im Block hast genauso wie die Funktionen innerhalb der Blöcke wenn sie
    eh nur im Block einmalig .laufen

    Die Doku zur Kodi API https://codedocs.xyz/xbmc/xbmc/group__python.html

    Und fürs nächste mal, sei mir bitte nicht böse, den Code säubern, sprich ungenutztes entweder löschen und kommentieren,
    damit machst Du es anderen leichter sich durchzuwurschteln.

    So, das soll es für das erste gewesen sein. :)

    Cheers
    Claudia

  • @ClaudiaF
    Oh mein Gott, das nenne ich mal eine echte ausführliche Hilfe. Ich hoffe mal das ich das auch verstehe und umsetzen kann.

    Ja der Code ist wirr und viel er ist gewachsen und ich dachte nicht im Traum das es so weit kommt.
    Ich werde mal sehen wie ich das umsetzen kann.
    Erstmal unfassbar danke.

  • %s erschliesst sich mir nicht und was genau hänge ich hinten dran?


    Ein Schrubfuhler:

    Code
    path=xbmc.TranslatePath(addon.getAddonInfo(%s).decode('utf-8') % (path))

    magst Du das etwas genauer erklären?

    Jetzt hast Du in path den entsprechend dem Dateisystem 'richtigen' Pfad (also C:\\wasweissich oder /home/user/keineahnung) und kannst path einfach weiter verweißwursten ;) dateiImAddonOrdner = os.path.join(path, unterordner, datei)

    AZi (DEV): Nexus auf LibreElec | Asrock J4205 | 4 GB RAM | 128 GB Sandisk| Rii mini
    DEV: PC Ubuntu 20.04 | Matrix
    AZi: Tanix TX3 | Android/CoreElec Dualboot (EMMC), Nexus
    WoZi: Nexus auf LibreElec | Asrock J4205 | 4GB RAM | 128 GB Sandisk SSD | Atric IR | URC7960

    NAS: unRaid, 3x6TB, 2x12TB | TV-Server: Futro S550 mit Hauppauge QuadHD DVB-C
    PayPal: paypal.me/pvdbj1


  • Jetzt hast Du in path den entsprechend dem Dateisystem 'richtigen' Pfad (also C:\\wasweissich oder /home/user/keineahnung) und kannst path einfach weiter verweißwursten ;) dateiImAddonOrdner = os.path.join(path, unterordner, datei)

    Ich glaube ich habe das genau so gemacht. :)

    @ClaudiaF
    Der QuellCode hat sich jetzt von 598 Zeilen auf 209 reduziert und es funktioniert.

    verstehe ich die Funktion def so richtig?;

    Python
    def open_image_and_display(image =Image.open(display).resize((disp.width, disp.height),
    Image.ANTIALIAS).convert('1')
       disp.image(image)


    und zum Aufrufen dann;

    Python
    try:
      open_image_and_display(display)
    except IOError:
      open_image_and_display(error)
  • Nein, Python erlaubt Dir auch Funktionen als Parameter zu nutzen aber diese müssen dann auch aufgerufen werden.

    Bezüglich Funtion als Parameter einer Funktion folgendes Beispiel:

    Python
    def a():
        print 'a'
        return 'a ist fertig'
    
    
    def b(parameter=a):
        print 'b'
        print parameter()

    Wenn Du nun die Funktion b aufrufst ohne einen Parameter zu übergeben also einfach mit

    b(), die Klammern sorgen dafür das Python weiß dass dies eine aufrufbare Funktion ist,

    dann bekommst Du als Ausgabe

    b
    a
    a ist fertig

    Wichtig ist hier die Zeile 7, parameter muß die Klammer haben damit der übergebene Parameter ausgeführt wird.
    Wenn Du nun aber eine andere Funktion, wie z.B. anonyme Fuktionen aufrufen würdest z. B.

    b(lambda:1+1)

    dann würde die Ausgabe so aussehen

    b
    2

    Zu deinem konkreten Fall, ich denke Du willst eine Funktion, die eigentlich so aussieht

    Python
    def open_image_and_display(image_path):
        image = Image.open(image_path).resize((disp.width, disp.height), Image.ANTIALIAS).convert('1')
        disp.image(image)

    Eine Funktion die als Parameter den Pfad zu einer Imagedatei erhält und dann dementsprechend ein Bild erzeugt und anzeigt.

    Du kannst nun auch die Funktion so ändern, dass Du einen Defaultwerte dem Parameter image_path zuweist ala

    Code
    def open_image_and_display(image_path='WOHIN_AUCH_IMMER'):
        image = Image.open(image_path).resize((disp.width, disp.height), Image.ANTIALIAS).convert('1')
        disp.image(image)


    Dann würde immer dann wenn Du nur

    open_image_and_display()

    aufrufst der Pfad WOHIN_AUCH_IMMER genommen um die Bilddatei zu lesen,
    ansonsten das was Du übergibst.

    Eine Sache die im Zusammenahng mit Funktionen und Variablen wichtig ist,
    Python kennt/nutzt das Konzept zu global und local Namespaces.
    Das heisst, das es einen definiert Namensraum gibt in dem eine Variable gültig ist
    und damit zugreifbar und änderbar ist.

    Funktionen definieren ihren eigenen lokalen Namensraum.
    Soll heissen, wenn Du eine Funktion hast die auf eine Variable zugreift die ausserhalb der Funktion
    definiert wurde kannst Du nur lesend darauf zugreifen. Wenn Du innerhalb einer Funktion eine
    Variable ändern willst die ausserhalb definiert wurde schlägt das fehl, ausser Du definierst vorher
    dass die Variable aus dem global Namespace kommt, mit dem statement global.


    Cheers
    Claudia

  • verstehe ich die Funktion def so richtig?;

    Ohne mich groß einmischen zu wollen und den Code gelesen zu haben...die Funktion heißt "open_image_and_display()" und in den Klammern stehen die Parameter, die du der Funktion mit gibst. Mit def definierst du nur, dass das nachfolgende eine Funktion ist.

    Frei nach dem Motto:


    Edit: zu langsam :D

  • ok, ich denke ich habe es verstanden.

    def {definiere eine funktion} irgend_ein_name_der_funktion(veränderbare_werte)
    code der ausgeführt werden soll

    irgend_ein_name_der_funktion() = nimmt den definierten wert falls vorhanden oder (mein_wert) den ich vorher festgelegt habe.

    cool.

  • irgendein_name_der_funktion() übergibt keine Werte an die danach folgenden Befehle. Du musst sozusagen einen Parameter in den Klammern definieren, den du dann auch weiter verwenden kannst. Sie mein Beispiel oben. Definiere ich den Parameter "text" nicht im Namen der Funktion kann ich ihn nicht weiter verwenden.

    Ich bin mir gerade unsicher, wie es sich mit globalen und lokalen Variablen verhält, ich weiß nur, dass Variablen innerhalb einer Funktion andere Werte haben kann, als außerhalb.

    Da kann Claudia oder BJ1 vielleicht mehr zu sagen.

  • Variablen innerhalb einer Funktion sind immer lokal, d.h. sie sind ausserhalb der Funktion unbekannt. Benötigt man sie dennoch ausserhalb, kann man sie innerhalb der Funktion als global definieren. Allerdings ist das für viele Programmierer ein NoGo (auch für mich). Der bessere Weg wäre dann - auch im Sinne der objektorientierten Programmierung - die Deklaration als Klassen- bzw. Objekteigenschaft (auch Property genannt).


    Ausgabe:


    Code
    --> "Hallo Welt"
    --> "Hallo User"

    AZi (DEV): Nexus auf LibreElec | Asrock J4205 | 4 GB RAM | 128 GB Sandisk| Rii mini
    DEV: PC Ubuntu 20.04 | Matrix
    AZi: Tanix TX3 | Android/CoreElec Dualboot (EMMC), Nexus
    WoZi: Nexus auf LibreElec | Asrock J4205 | 4GB RAM | 128 GB Sandisk SSD | Atric IR | URC7960

    NAS: unRaid, 3x6TB, 2x12TB | TV-Server: Futro S550 mit Hauppauge QuadHD DVB-C
    PayPal: paypal.me/pvdbj1

  • @tjost

    um dich nun ganz zu verwirren :) , globale variablen haben natürlich ihre Existenzberechtigung,
    aber wie schon BJ1 richtig sagt, sind sie nicht gern gesehen.

    Wer sich aber mal in der Standardbibliothek umsieht, wird des öfteren darauf treffen.
    Und wenn diese richtig eingesetzt werden, dann gibt es, aus meiner Sicht, keinen Grund sie zu meiden.

    Meines Wissens sind globale Variablen in einem Modul der einzige sichere Weg um zum Beispiel eine Singleton-Klasse abzubilden.

    Was aber ein NoGo ist, und da gebe ich wiederum BJ1 Recht, ist eine Variable in einer Funktion
    als global zu definieren um diese dann modulweit bekanntzumachen.
    Nein, dann sofort auf Modulebene defnieren.

    Das ist aber für den Anfang, meiner Meinung nach, für dich noch nicht wirklich interessant.
    Du solltest wissen das es die Unterschiede gibt damit Du weißt wie Du darauf reagieren kannst.

    Cheers
    Claudia

  • neue version

    hallo nochmal,

    also wie und wo ich "waitForAbort" einbauen soll habe ich noch nicht herausgefunden. Aber so funktioniert es ja und aktualisiert sich ja auch.
    was das wechseln des Textes angeht habe ich es mal so probiert;

    Python
    if PlayerisMovies==True:
         create_and_display_image(systemtime, videotime)
         time.sleep(5)
         create_and_display_image(systemdate, videotime)

    funktioniert aber nicht, er überspringt die erste Angabe und zeigt nur die 2. Sollte man da vielleicht doch ein pass oder so einfügen?

    5 Mal editiert, zuletzt von tjost (22. Januar 2018 um 19:06)

  • Datei kann ich nicht laden, ftp error 533 prohibited file name

    Daher die Infos bezogen auf deine vorherige Version.

    Du hattest da ein while True:
    was letztendlich bedeutet: laufe IMMER die Schleife durch.

    Gut das Kodi das Script in einem eigenen Thread startet, ansonsten würde,
    wenn das Script im Mainloop Thread läuft, nichts mehr funktionieren ausser diesem Script.

    Wenn nun Kodi gestoppt werden soll, informiert Kodi die laufenden Threads darüber, nur dein
    Thread hat nichts anders zu tun als in der Schleife zu laufen. Früher oder später wird Kodi, den thread terminieren
    aber das ist nicht wirklich die feine Art, oder?

    Damit das Script nun die Möglichkeit hat sauber zu enden, müsstest Du also ein waitForAbort einsetzen damit deine while Schleife
    abgebrochen werden kann. Siehe https://codedocs.xyz/xbmc/xbmc/grou…06abcda904e8249

    In etwa

    while not xbmc.Monitor().waitForAbort(2):
    ...

    Damit wird für 2 Sekunden gewartet ob Kodi terminieren will, wenn nicht die Schleife weiter abarbeiten

    Du kannst dein while True behalten, solltest aber wissen, dass wenn Du Dateien bearbeitest währendessen dir Kodi deinen Thread terminiert,
    diese korrumpiert werden können. Also ich würde lieber waitForAbort nehmen.

    Zum anderen Problem, höchstwahrscheinlich blockt der time.sleep(5) den ersten DisplayUpdate.
    Evtl. mal xmbc.sleep probieren (siehe https://codedocs.xyz/xbmc/xbmc/grou…ec4a7a5a1073e7e),
    vlt. blockiert das den Update nicht oder den Weg gehen, den ich vorher vorgeschlagen habe.
    Vorsicht, xbmc.sleep nutzt msec also 2000 für 2 Sekunden angeben.

    Cheers
    Claudia

  • aber wie schon BJ1 richtig sagt, sind sie nicht gern gesehen.

    Ich glaube, was @BJ1 meinte war, dass es nicht gern gesehen ist, wenn man Variablen innerhalb einer Funktion als globale Variable definiert. Wahrscheinlich einfach aus Gründen der Lesbarkeit oder auch der Gefahr, dass eine zuvor global gesetzt Variable überschrieben werden könnte.

    Ich wüsste nicht, was grundsätzlich gegen globale Variablen sprechen würde.

  • @DaVu
    verstehe jetzt nicht ganz was Du meinst.
    Variablen sind grundsätzlich implizit global, erst wenn eine Zuweisung erfolgt könnte aus einer globalen Variable
    eine lokale werden.
    Wenn ich auf Modulebene eine Variable definiere und diese dann in einer Funktion mit global referenziere dann
    überschreibe ich diese nicht, sondern verweise darauf.

    Python
    g_var = 0
    
    
    def x():
        global g_var
        g_var = 1


    g_var innerhalb von der Funktion x ist KEINE neue Variable, sondern g_var von vorher.

    Python
    g_var = 0
    
    
    def y():
        global neue_variable
        neue_variable = 1

    Jetzt wird in der Funktion y eine neue Variable definiert und global gesetzt die vorher nicht bekannt war.
    Das ist ein NoGo.

    So, jetzt wird Essen gemacht. :D

    Cheers
    Claudia

  • Dein erstes Beispiel zeigt es doch ganz gut...


    Ausgabe:

    Code
    1
    0
    1

    glo_var hat also innerhalb der Funktion einen anderen Wert als außerhalb.


    Variablen sind grundsätzlich implizit global

    Das würde ich so nicht unterschreiben:

    loc_var ist außerhalb der Funktion nicht verfügbar, solange nicht nicht als "global" definiert wurde.

    Wenn ich innerhalb der Funktion (also lokal) eine Funktion als global setze, die es außerhalb der Funktion schon bestand. Bekomme ich ein Syntax Warning mit dem Hinweis, dass es die Variable schon gibt (globale Variable) :


    "
    ./global.py:8: SyntaxWarning: name 'glo_var' is assigned to before global declaration"

  • ./global.py:8: SyntaxWarning: name 'glo_var' is assigned to before global declaration"

    Das sagt nur aus, dass Du den Wert der Variablen verändert hast, bevor sie als global deklariert wurde. Das ist Mumpitz ;) . Normalerweise deklariert man erst eine Variable (als global) bevor man ihr einen Wert zuweist und nicht umgedreht - deshalb die Warnung.

    AZi (DEV): Nexus auf LibreElec | Asrock J4205 | 4 GB RAM | 128 GB Sandisk| Rii mini
    DEV: PC Ubuntu 20.04 | Matrix
    AZi: Tanix TX3 | Android/CoreElec Dualboot (EMMC), Nexus
    WoZi: Nexus auf LibreElec | Asrock J4205 | 4GB RAM | 128 GB Sandisk SSD | Atric IR | URC7960

    NAS: unRaid, 3x6TB, 2x12TB | TV-Server: Futro S550 mit Hauppauge QuadHD DVB-C
    PayPal: paypal.me/pvdbj1

  • Hallo Claudia

    ersteinmal vielen Dank für die Mühe die Du dir gibst. Der Link ist gefixt.

    Also ich habe alles in einer while true schleife damit die Logos beim Kanalwechsel auch neu angezeigt werden.
    Ich habe keine Ahnung wie ich das sonst lösen kann. Da fehlen mir leider die Kenntnisse.

    while not xbmc.Monitor().waitForAbort(2): anstelle des while True scheint zu funtkionieren. Danke


    Python
    if window=="10000":
    					xbmc.sleep(50)
    					create_and_display_image(systemday, systemdate, font28)
    					xbmc.sleep(5000)
    					create_and_display_image(systemtime, systemdate)

    funktioniert auch nicht. Hier müsste ich ich denke ich eine Schleife einbauen die nur durchläuft solange window=="10000" ist.
    Ich denke vielleicht eine for Schleife? Aber keine Ahnung wie.

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!