Python: hoe object vaker raadplegen dan updaten?

Pagina: 1
Acties:

Vraag


Acties:
  • +3 Henk 'm!

  • pmeter
  • Registratie: December 2001
  • Laatst online: 18-09 21:51
Als hobbyproject (ik ben geen programmeur en ben onlangs met Python begonnen) ben ik bezig met een frontend voor een Bluesound muziekspeler. Ik loop tegen het probleem aan dat de code traag is. Als je bij een invoerveld iets invult, dan verschijnt het met een vertraging. En als ik het venster in Windows versleep, dan gaat dat met schokken. Dat gebeurt al als ik de GUI 1 keer per seconde laat updaten. Als ik de GUI 5 keer per seconde laat updaten, dan start het programma niet eens op. Als ik de GUI 1 keer per 10 seconden laat updaten, dan is de vertraging opgelost. Maar ja, dan loopt de GUI (waaronder ook een progressbar) achter.

De code laat 8 GUI-onderdelen (de progressbar, het nu spelende nummer, de playlist etc) 1 keer per seconde updaten met de 'after' functie. Zie hieronder als voorbeeld de code waarmee achterhaald wordt of de muziekspeler op repeat staat of niet. De GUI (de bovenste code) voert 1 keer per seconde de method Status().check_repeat() uit. Die method staat onderaan weergegeven.

Omdat 8 GUI-onderdelen geüpdated moeten worden, wordt de netwerkspeler 8 keer per seconde om zijn status gevraagd door de code urllib.request.urlopen("http://" + ip + ":11000/Status", waarna de muziekspeler zijn status in XML-formaat terugstuurt. Ik vermoed dat de traagheid veroorzaakt wordt doordat de muziekspeler 8 keer per seconde om zijn status wordt gevraagd.

Vraag: ik wil de onderste code zodanig wijzigen dat de netwerkspeler slechts 1 keer per seconde om de status wordt gevraagd, ondanks dat 8 onderdelen van de GUI daar 1 keer per seconde om vragen. Dus ik wil elke seconde 8 keer hetzelfde 'antwoord' doorgeven. Maar ik weet niet hoe ik dat voor elkaar krijg.

Een stukje code van de GUI (Tkinter-bibliotheek). Zie vooral de laatste regel.
Python:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Frame_repeat_status(Frame3)
    def __init__(self, parent):
        tk.Frame.__init__(self, parent, bg="black")
        self.parent = Frame3L2
        self.widgets()

    def widgets(self):
        self.q = tk.Button(self)
        self.q.status = tk.Button(self, command=Control().repeattoggle, bg="black", fg="#FFF8DC")
        self.q.status.configure(text="Repeat: " + Status().check_repeat())
        self.q.status.place(x=0, y=0, rely=0, relwidth=1, relheight=1, height=0)

        self.update()

    def update(self):
        self.q.status.configure(text="Repeat: " + Status().check_repeat())
        self.after(1000, self.update)


Een stukje van de hiermee aangeroepen class:
Python:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Status():
    def __init__(self):
        self.status_xml = urllib.request.urlopen("http://" + ip + ":11000/Status")
        self.status_parsed = minidom.parse(self.status_xml)

    def check_repeat(self):
        try:
            status_elements = self.status_parsed.getElementsByTagName("repeat")[0]
            repeat = status_elements.firstChild.data
            if repeat == "0":
                return "ON"
            if repeat == "1":
                return "1"
            if repeat == "2":
                return "OFF"
        except IndexError as error:
            return ""


De GUI:
GUI van client in python

[ Voor 6% gewijzigd door pmeter op 21-08-2019 15:37 ]

Alle reacties


  • Gomez12
  • Registratie: Maart 2001
  • Laatst online: 17-10-2023
Waarom initialiseer je je status elke keer opnieuw?

Je status lijkt mij een method/property van iets anders.

Want door het telkens te initialiseren kan je moeilijk je status behouden. Oftewel ik zou zeggen zorg er eerst voor dat de status niet meer geinitialiseerd wordt, dan kan je gewoon binnen je statusaanvragen een tellertje of een timertje bijhouden die elke 8 aanroepen (of bijv 8 seconden) de echte externe status wegzet in een variabele en je standaard status aanroep die geeft alleen maar die variabele terug.

  • pmeter
  • Registratie: December 2001
  • Laatst online: 18-09 21:51
Dank! Alleen hoe zet ik iets weg in een variabele zonder dat het aanroepen van die variabele de method uitvoert?

Voor de zekerheid: het gaat niet om een string of integer, maar om de output van minidom.parse(self.status_xml) die ik self.status_parsed heb genoemd.

[ Voor 18% gewijzigd door pmeter op 15-08-2019 10:46 ]


  • Gomez12
  • Registratie: Maart 2001
  • Laatst online: 17-10-2023
[pseudocode]
--Ergens hiervoor moet je dus een string definieren die "globaal" geldig is

if counter>=8 or string is null then
string = minidom.parse(self.status_xml)
counter=0
counter++
return string
[/pseudocode]
Oftewel het gaat wel om een string of een integer, want ipv het elke keer te parsen buffer je het in een string variabele en als die 8x is uitgelezen dan ga je pas opnieuw parsen.

  • CCJJVV
  • Registratie: Maart 2016
  • Laatst online: 04-10 18:01
Het probleem ligt denk ik niet zo zeer bij het 8 keer opvragen van de status maar bij de manier waarop deze opgevraagd wordt. Zie bijvoorbeeld https://docs.python.org/3...llib-request-restrictions, hierin wordt o.a. het volgende gezegd:
The urlopen() and urlretrieve() functions can cause arbitrarily long delays while waiting for a network connection to be set up. This means that it is difficult to build an interactive Web client using these functions without using threads.
Voor zover ik kan zien maak jij geen gebruik van threading. Wanneer een request er 250ms over doet om voltooid te worden dan kunnen er dus maximaal 4 requests per seconden afgehandeld worden.

  • Raynman
  • Registratie: Augustus 2004
  • Laatst online: 19:33
Ook als je die request in een thread op de achtergrond doet, wil je dat natuurlijk liever niet 8x doen als 1x genoeg is.
Gomez12 schreef op donderdag 15 augustus 2019 @ 13:36:
Oftewel het gaat wel om een string of een integer, want ipv het elke keer te parsen buffer je het in een string variabele en als die 8x is uitgelezen dan ga je pas opnieuw parsen.
Het resultaat van het parsen is in dit geval een minidom Document en geen string of integer, maar het precieze type maakt verder niet veel uit voor de opzet. Dat hoeft natuurlijk niet per se een globaal object te zijn, maar we hebben niet de volledige code en ik heb ook geen ervaring met Tkinter. Ook die 8 hardcoden is niet heel handig. Je zou ook een lijst met de te updaten objecten kunnen hebben en dan één functie die de request doet, het resultaat parset en dan voor elk object in die lijst een update() methode aanroept met het XML-document als parameter.

  • CCJJVV
  • Registratie: Maart 2016
  • Laatst online: 04-10 18:01
Raynman schreef op donderdag 15 augustus 2019 @ 14:10:
Ook als je die request in een thread op de achtergrond doet, wil je dat natuurlijk liever niet 8x doen als 1x genoeg is.

[...]

Het resultaat van het parsen is in dit geval een minidom Document en geen string of integer, maar het precieze type maakt verder niet veel uit voor de opzet. Dat hoeft natuurlijk niet per se een globaal object te zijn, maar we hebben niet de volledige code en ik heb ook geen ervaring met Tkinter. Ook die 8 hardcoden is niet heel handig. Je zou ook een lijst met de te updaten objecten kunnen hebben en dan één functie die de request doet, het resultaat parset en dan voor elk object in die lijst een update() methode aanroept met het XML-document als parameter.
Uiteraard wil je het liever een request 8x doen als je zeker weet dat 8x het zelfde binnenkomt en 1x dus genoeg is. Het probleem dat TS echter wil oplossen ligt in mijn ogen niet perse bij de het 8x uitvoeren van de request(al versterkt het 8x uitvoeren van de request wel het probleem).

  • Gomez12
  • Registratie: Maart 2001
  • Laatst online: 17-10-2023
Raynman schreef op donderdag 15 augustus 2019 @ 14:10:
Ook die 8 hardcoden is niet heel handig. Je zou ook een lijst met de te updaten objecten kunnen hebben en dan één functie die de request doet, het resultaat parset en dan voor elk object in die lijst een update() methode aanroept met het XML-document als parameter.
Ik zou helemaal geen lijstjes oid bij gaan houden. Je wilt gewoon niet hebben dat elk GUI-dingetje zijn eigen data-calls doet.

Je wilt gewoon 1 method hebben die je data-call doet en de uitkomst van die data-call wil je bufferen binnen je app. Zodat al je GUI-elementen probleemloos je buffer uit kunnen lezen.

En ik zou het wel bufferen in een string oid ipv in een minidom, het telkens weer parsen van een minidom is simpelweg niet gratis. Terwijl de uitkomst gelijk blijft.

En door maar 1 method te hebben die je data-call doet en die je buffer vernieuwt kan je ook perfect gaan multi-threaden op die ene method, want al duurt die data-call dan 10 seconden, je GUI ondervindt er geen last van (want die leest uit je buffer) alleen je data loopt 10 seconden achter dan.

  • Raynman
  • Registratie: Augustus 2004
  • Laatst online: 19:33
Volgens mij zijn we het grotendeels eens. Inderdaad kan de request naar een thread verplaatsen dan een makkelijkere vervolgstap zijn. Ik vond het hoogstens jammer dat @CCJJVV dat er meteen al bij trekt, terwijl TS nog genoeg moeite lijkt te hebben het overzicht te houden binnen een enkele thread.

Maar een stukje volg ik niet helemaal:
Gomez12 schreef op donderdag 15 augustus 2019 @ 14:34:
[...]

En ik zou het wel bufferen in een string oid ipv in een minidom, het telkens weer parsen van een minidom is simpelweg niet gratis. Terwijl de uitkomst gelijk blijft.
Zoals ik de TS begrijp, wil-ie elke seconde een request doen voor een (mogelijk gewijzigde) status. Dat levert XML op en die wordt geparset naar minidom. Elk GUI-element vist vervolgens uit die minidom de voor dat element relevante data (in de gegeven code wordt concreet de button text voor repeat aangepast). Maar in de huidige opzet wordt het requesten en parsen naar minidom voor elk element opnieuw gedaan, terwijl dat makkelijk terugbracht moet kunnen worden naar een keer.

Waar zie jij dan nog "telkens weer parsen van minidom terwijl de uitkomst gelijk blijft". Uiteraard zal de repeat-status en huidige track niet elke seconde veranderen, maar de XML wordt toch geparset voor de progressbar, of wou je ingrijpendere wijzigingen voorstellen?

  • pmeter
  • Registratie: December 2001
  • Laatst online: 18-09 21:51
Edit: het werkt nog niet. Zie mijn volgende post.

[ Voor 255% gewijzigd door pmeter op 15-08-2019 23:36 ]


  • Gomez12
  • Registratie: Maart 2001
  • Laatst online: 17-10-2023
Raynman schreef op donderdag 15 augustus 2019 @ 15:05:
Zoals ik de TS begrijp, wil-ie elke seconde een request doen voor een (mogelijk gewijzigde) status. Dat levert XML op en die wordt geparset naar minidom. Elk GUI-element vist vervolgens uit die minidom de voor dat element relevante data (in de gegeven code wordt concreet de button text voor repeat aangepast). Maar in de huidige opzet wordt het requesten en parsen naar minidom voor elk element opnieuw gedaan, terwijl dat makkelijk terugbracht moet kunnen worden naar een keer.

Waar zie jij dan nog "telkens weer parsen van minidom terwijl de uitkomst gelijk blijft".
In het bold stukje, dom-parsers zijn per definitie (puur vanuit wat ze moeten doen) lomp en inefficient.
Dan kan je het leuk verhullen door het mini-dom te noemen etc, maar het blijft een relatief zware actie die je maar 1x wilt doen ipv 8x.

  • pmeter
  • Registratie: December 2001
  • Laatst online: 18-09 21:51
Ik doe nu de dom-parser maar één keer per seconde. Maar het werkt nog niet. Ik blijf zitten met de vraag hoe ik de status van een van de 8 onderdelen - die strings zijn - als een variabele kan opslaan. Wat nu gebeurt is dat als ik in de GUI de method check_repeat aanhaal en daarmee de variabele self.repeat_temp gebruik, toch elke keer urllib.request.urlopen wordt uitgevoerd.

Onderstaande code is alleen een test om te zien of self.repeat_temp een 'zelfstandig bestaan leidt' als variable. Dat doet hij niet. Want het aanhalen daarvan voert code uit.

Python:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Status():
    def __init__(self):
        self.statusupdate()
        
    def statusupdate(self):
        self.status_xml = urllib.request.urlopen("http://" + ip + ":11000/Status")
        self.status_parsed = minidom.parse(self.status_xml)

        #check_repeat
        self.repeat_new = ""
        self.repeat_temp = ""
        try:
            status_elements = self.status_parsed.getElementsByTagName("repeat")[0]
            self.repeat_new = status_elements.firstChild.data
            self.repeat_temp = self.repeat_new
        except IndexError as error:
            None

    def check_repeat(self):
        try:
            if self.repeat_temp == "0":
                return "ON"
            if self.repeat_temp == "1":
                return "1"
            if self.repeat_temp == "2":
                return "OFF"
        except IndexError as error:
            return ""


Ik begrijp niet waarom dat gebeurt, want onderstaande code levert "1" op. Kennelijk bevriest x wel. Ik bedoel x wordt niet geupdated als y dat wordt. Waarom werkt dat hierboven niet zo met self.repeat_temp?
Python:
1
2
3
4
x = 1
y = x
x = 2
print(y)

[ Voor 10% gewijzigd door pmeter op 15-08-2019 21:07 ]


Acties:
  • +1 Henk 'm!

  • Morrar
  • Registratie: Juni 2002
  • Laatst online: 14:45
Als je bovenstaande klasse aanroept met Status().check_repeat() zoals in je eerste post, dan zorgt die Status() ervoor dat de __init__() van je klasse aangeroepen wordt. En in die __init__() roep je statusupdate() aan, die vervolgens een request via urllib doet...

Als je het aantal requests wilt limiteren, dan zou je ook de datetime van de laatste update kunnen opslaan in je klasse. Je doet dan alleen een nieuwe request als die datetime meer dan X seconden geleden is.

Als meerdere functies / classes gebruik moeten maken van je Status klasse, zou je er een singleton van kunnen maken. Dit is in Python niet heel straight forward, maar wel te doen zie bv.: https://stackoverflow.com...ing-a-singleton-in-python

Demootje van het geheel:
Python:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import time
import datetime as dt


class Singleton(type):
    """Implements singeton as metaclass."""

    _instances = {}
    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
        return cls._instances[cls]

class Status(metaclass=Singleton):
    """Checks status at regular intervals."""
    
    def __init__(self, freq=10):
        """Constructor, set update frequency in seconds."""
        self._freq = 10        
        self._status = 0
        self._last_update = dt.datetime.now()
        
    def _update_status(self):
        """Perform status update if status has expired."""
        delta = dt.datetime.now() - self._last_update
        if delta.total_seconds() > self._freq:
            self._status += 1
            self._last_update = dt.datetime.now()

    def get_status(self):
        """Returns most recent status."""
        self._update_status()
        return self._status
    
class Caller:
    """Caller class uses above Status class."""
    
    def __init__(self):    
        self._status = Status()
    
    def update(self):
        print(self._status.get_status())


# Create 2 callers
caller1 = Caller()
caller2 = Caller()

# Note how both callers have the same Status object (singleton).
# Having only a single Status object limits the overall _update_status() calls.
print(id(caller1._status), id(caller2._status))

# Loop every second, watch the status change every 10 seconds
for i in range(1, 100):
    caller1.update()
    caller2.update()
    time.sleep(1)

[ Voor 114% gewijzigd door Morrar op 15-08-2019 20:48 ]


Acties:
  • +1 Henk 'm!

  • pmeter
  • Registratie: December 2001
  • Laatst online: 18-09 21:51
Dankzij jullie is het probleem opgelost. :)

Naast de status-update zorgde ook de playlist-update voor vertraging. Er waren bij elkaar 18 get requests per seconde. Met de singleton class zoals voorgesteld door Morrar heb ik dat gereduceerd tot 2 get-requests per seconde. Er zijn nu twee singleton classes. Een voor de playlist (die wel honderden nummers lang kan zijn) en een voor de status (de overige GUI-elementen). Daarnaast heb ik zoals door Gomez12 voorgesteld de minidom-functie alleen die 2 keer laten uitvoeren en niet 18 keer.

Het programma is nu heerlijk responsief 8)

[ Voor 31% gewijzigd door pmeter op 16-08-2019 10:51 ]


Acties:
  • 0 Henk 'm!

  • pmeter
  • Registratie: December 2001
  • Laatst online: 18-09 21:51
Gomez12 schreef op donderdag 15 augustus 2019 @ 09:53:
Waarom initialiseer je je status elke keer opnieuw?

Je status lijkt mij een method/property van iets anders.

Want door het telkens te initialiseren kan je moeilijk je status behouden. Oftewel ik zou zeggen zorg er eerst voor dat de status niet meer geinitialiseerd wordt, dan kan je gewoon binnen je statusaanvragen een tellertje of een timertje bijhouden die elke 8 aanroepen (of bijv 8 seconden) de echte externe status wegzet in een variabele en je standaard status aanroep die geeft alleen maar die variabele terug.
Hoewel het nu werkt met een singleton, ben ik benieuwd of er een eenvoudiger methode bestaat. Is het mogelijk om de check_repeat() method aan te halen zonder de Status() class opnieuw te initialiseren? Anders gevraagd: hoe zet ik iets weg in een variabele zonder dat het aanroepen van die variabele de code uitvoert waar die variabele naar verwijst? Daarbij gaat het me niet om de timer. Die is relatief eenvoudig. Maar hoe laat ik de timer-code een gebufferde status teruggeven. Dat laatste weet ik niet.

[ Voor 17% gewijzigd door pmeter op 19-08-2019 16:54 ]


Acties:
  • +1 Henk 'm!

  • Morrar
  • Registratie: Juni 2002
  • Laatst online: 14:45
Alles hangt natuurlijk samen met waar je die Status-klasse nodig hebt. Als je de Status-klasse maar op 1 plek gebruikt, heb je geen singleton nodig. Dan kun je de Status gewoon opslaan in de aanroepende klasse:

Python:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Status:

    def __init__(self):
        # Doe initiele status update
        self._update_status()

    def _update_status(self):
        # Update status met urllib request
        print("Updating status")

    def get_status(self):
        # Doet self._update_status() als nodig
        # Retourneert gebufferde status
        print("Getting status")

class Caller:
    
    def __init__(self):
        # Initialisatie Status klasse
        self._status = Status()

    def update(self):
        # Alleen aanroepen get_status() methode
        self._status.get_status()


Het probleem ontstaat als er twee Caller instances zijn; die hebben dan beiden een eigen status instance die beiden _update_status() status doen, probeer maar:

Python:
1
2
3
4
5
caller1 = Caller()
caller2 = Caller()

# Verschillende IDs
print(id(caller1._status), id(caller2._status))


Als je 1 Status instance wilt delen tussen meerdere Caller instances, dan zijn er twee opties; globale variabelen of singletons. Globale variabelen wordt al snel een zootje als je even vergeet ze globaal te maken :)

[ Voor 14% gewijzigd door Morrar op 19-08-2019 16:55 ]


Acties:
  • 0 Henk 'm!

  • pmeter
  • Registratie: December 2001
  • Laatst online: 18-09 21:51
Morrar schreef op maandag 19 augustus 2019 @ 16:46:
Alles hangt natuurlijk samen met waar je die Status-klasse nodig hebt. Als je de Status-klasse maar op 1 plek gebruikt, heb je geen singleton nodig. Dan kun je de Status gewoon opslaan in de aanroepende klasse:
(...)

Het probleem ontstaat als er twee Caller instances zijn; die hebben dan beiden een eigen status instance die beiden _update_status() status doen, probeer maar:

(...)

Als je 1 Status instance wilt delen tussen meerdere Caller instances, dan zijn er twee opties; globale variabelen of singletons. Globale variabelen wordt al snel een zootje als je even vergeet ze globaal te maken :)
Ik wil inderdaad dezelfde instantie van de Status() class vanuit meerdere andere classes aanroepen. Dan is het dus kiezen uit twee kwaden.

Acties:
  • 0 Henk 'm!

  • Morrar
  • Registratie: Juni 2002
  • Laatst online: 14:45
pmeter schreef op maandag 19 augustus 2019 @ 16:58:
[...]

Ik wil inderdaad dezelfde instantie van de Status() class vanuit meerdere andere classes aanroepen. Dan is het dus kiezen uit twee kwaden.
Ik vrees het wel. Je zult dan altijd een Status instance moeten opslaan in een namespace buiten de twee aanroepende instances...

Acties:
  • 0 Henk 'm!

  • pmeter
  • Registratie: December 2001
  • Laatst online: 18-09 21:51
Ik heb een andere oplossing gevonden die volgens een kennis netter is. Daarbij zijn geen singletons en globale variabelen nodig. Het komt erop neer dat je de class Status eenmaal initialiseert in de class Main. En dat je vanuit de class Main die instantie van Status als argument meegeeft aan de andere classes die methoden uit de class Status nodig hebben. Hieronder de code.

Python:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
class Main(tk.Tk):

    def __init__(self, parent=None):
        tk.Tk.__init__(self, parent)

        (...)

        self.setframes()

    def setframes(self):

        self.status = Status()
        self.control = Control(self.status)

        self.frame3 = Frame3(self, self.status, self.control)
                
        (...)
    
class Frame3(tk.Frame):
    def __init__(self, parent, status, control):

        (...)

        self.parent = parent
        self.status = status
        self.control = control      

        self.setsubframes3L()

    def setsubframes3L(self):

        (...)
        self.frame3L2 = Frame3L2(self, self.status, self.control)
        
        (...)

class Frame3L2(tk.Frame): # quality, repeat, shuffle
    def __init__(self, parent, status, control):
        
        (...)        
        
        self.parent = Frame3
        self.status = status
        self.control = control   
        self.setsubframes3L2()

    def setsubframes3L2(self):   

        self.frame3L2R = Frame3L2R(self, self.status, self.control)
        (...)

(...)

class Frame3L2R(tk.Frame): # repeat
    def __init__(self, parent, status, control):
        
        (...)
        
        self.parent = Frame3L2
        self.status = status
        self.control = control  
        self.widgets()

    def widgets(self):
        self.r = tk.Button(self)
        self.r.status = tk.Button(self, command=self.control.repeattoggle)
        self.r.status.configure(text="R: " + self.status.check_repeat())
        self.r.status.place(x=0, y=0, rely=0, relwidth=1, relheight=1, height=0)

        self.update()

    def update(self):
        self.r.status.configure(text="R: " + self.status.check_repeat())
        self.after(GUI_UPDATE_DELAY, self.update)  

(...)

class Status(object):
    def __init__(self, interval=0.5):
        self._interval = interval
        self._last_update = None
        self.status_parsed = None
        print("Status() initialized at " + str(dt.datetime.now()))

    def _update_status(self):
        if (self._last_update is None) or ((dt.datetime.now() - self._last_update).total_seconds() > self._interval):
            self.status_xml = urllib.request.urlopen(base_url + "Status")
            self.status_parsed = minidom.parse(self.status_xml)
            self._last_update = dt.datetime.now()

    def get_status(self):
        self._update_status()
        return self.status_parsed

    def get_status(self):
        """Returns most recent status."""
        self._update_status()
        return self.status_parsed

    def check_repeat(self):
        try:
            status_elements = self.get_status().getElementsByTagName("repeat")[0]
            repeat = status_elements.firstChild.data
            if repeat == "0":
                return "ON"
            if repeat == "1":
                return "1"
            if repeat == "2":
                return "OFF"
        except IndexError as error:
            return ""

if __name__=="__main__":
    app = Main(None)
    app.mainloop()

Acties:
  • 0 Henk 'm!

  • Morrar
  • Registratie: Juni 2002
  • Laatst online: 14:45
Doorgeven uit een hogere namespace kan inderdaad ook bedacht ik me later... Idee is vergelijkbaar met global, maar wel veel netter inderdaad. Singleton vind ik zelf ongeveer even netjes, maar heeft iets meer boilerplate code nodig in Python.

MIsschien nog te overvloede, maar waar je bij ale oplossingen op moet letten is dat als een aanroepende instance het status object wijzigt, dit ook doorwerkt naar alle andere aanroepende instances.

[ Voor 29% gewijzigd door Morrar op 24-08-2019 16:05 ]

Pagina: 1