darts.util.events er en Python bibliotek som gir en enkel hendelse sentralen, lik den hendelsen konstruere levert av C # språket. & Nbsp; Biblioteket har ingen eksterne avhengigheter.
Det var ment for bruk tilfeller, der komponentene emitting hendelser og komponentene lytter til arrangementer enige om hendelsestype og semantikk knyttet til den. Dette gjelder for eksempel for hendelsesbehandlinger, som lytter på "klikk" hendelser signalisert GUI knappeobjekter eller varslinger signalisert av gjenstander, når verdien av enkelte eiendoms endringer. Dette skiller seg fra tilnærmingen tatt av, si, PyDispatcher, som er mer generisk, og favoriserer kommunikasjon mellom svakt koblede komponenter.
Kompatibilitet
Koden ble skrevet for og testet med Python 2.6. Det bør være kompatibel med 2.5 også, men du må kanskje sette inn noen fra __future__ import with_statement linjer her og der. Det skal fungere (dette er ikke testet) med alternative implementeringer av Python som Jython eller Ironpython. Legg imidlertid merke til at noen av testtilfeller definert i denne filen kan mislykkes på grunn av forskjellige søppelrydding implementeringer; denne filen ble skrevet med CPython i tankene.
Dokumentasjon
Grunnleggende bruk
& Nbsp; >>> fra darts.lib.utils.event import Publisher, ReferenceRetention som RR
& Nbsp; >>> some_event = Publisher ()
Utgiver er den viktigste komponenten. Det fungerer som registeret tilbakeringing / lyttere. La oss definere en lytter
& Nbsp; >>> def skriver (* event_args, ** event_keys):
& Nbsp; ... Skriv event_args, event_keys
For å motta varslinger, må kundene abonnere på en utgiver. Dette kan være så enkelt som å
& Nbsp; >>> some_event.subscribe (skriver) #doctest: + ellipse
& Nbsp;
Resultatet av samtalen til å tegne er en forekomst av (noen underklasse av) klassen abonnement. Denne verdien kan brukes senere, for å kansellere abonnementet, når meldinger er ikke lenger ønsket. Selve underklasse er en implementering detalj du bør normalt ikke bryr seg om. Alt du trenger å vite (og får lov til å stole på, faktisk) er, at det vil være en forekomst av klassen abonnement, og det vil gi det som er dokumentert som offentlig API av klassen (akkurat nå: eneste metoden avbryte) .
Nå, la signalisere en hendelse, og se hva som skjer:
& Nbsp; >>> some_event.publish ('an-event')
& Nbsp; ('an-event ",) {}
Som du kan se, er skriveren er varslet om hendelsen, og duefully skrevet ut sine argumenter til konsollen.
Avbryte abonnementer
Som nevnt, er resultatet av å kalle tegne et spesielt abonnement objekt, som representerer registrering av lytteren med utgiveren.
& Nbsp; >>> s1 = some_event.subscribe (skriver)
& Nbsp; >>> some_event.publish ('annen hendelse')
& Nbsp; ('another-event ",) {}
& Nbsp; ('another-event ",) {}
& Nbsp; >>> s1.cancel ()
& Nbsp; Sann
& Nbsp; >>> some_event.publish ("ennå-another-ett")
& Nbsp; ("ennå-another-ett",) {}
Utgiveren er helt re-deltaker. Det betyr at du kan abonnere på hendelser innenfra en lytter, og du kan avbryte abonnementer i den sammenheng også:
& Nbsp; >>> def make_canceller (subs):
& Nbsp; ... def lytteren (* unused_1, ** unused_2):
& Nbsp; ... print "Avbryt", ubåter, subs.cancel ()
& Nbsp; ... retur lytteren
& Nbsp; >>> s1 = some_event.subscribe (skriver)
& Nbsp; >>> s2 = some_event.subscribe (make_canceller (s1))
& Nbsp; >>> some_event.publish ('må-go ") #doctest: + ellipse
& Nbsp; ('må-go ",) {}
& Nbsp; ('må-go ",) {}
& Nbsp; Avbryt
& Nbsp; >>> some_event.publish ('borte') #doctest: + ellipse
& Nbsp; ('borte',) {}
& Nbsp; Avbryt
& Nbsp; >>> s1.cancel ()
& Nbsp; False
Resultatet av samtalen for å avbryte forteller oss at abonnementet hadde allerede blitt ugjort før samtalen (etter vår magi avbestillings lytteren). Vanligvis ringer avbryte flere ganger er ufarlig; alle, men den første samtalen blir ignorert.
La oss nå fjerne den magiske I-kan-kansellere-stuff lytteren og gå videre:
& Nbsp; >>> s2.cancel ()
& Nbsp; Sann
Ved hjelp av Non-Callables som callbacks
Når vi har gjort abonnementer ovenfor, vi faktisk simplied ting litt. Den fullstendige signaturen til metoden er:
& Nbsp; def abonnere (lytteren [, metode [, reference_retention]])
La oss utforske metoden argument først. Frem til nå har vi bare brukt funksjonsobjekter som lyttere. I utgangspunktet, faktisk, vi kunne ha brukt noen callable objekt. Husk at et objekt er "Callable" i Python, hvis det gir en __call__ metode, så antar jeg, hva er standardverdien av metoden argument?
& Nbsp; >>> s1 = some_event.subscribe (skriver, method = '__ call__')
& Nbsp; >>> some_event.publish ('foo')
& Nbsp; ('foo',) {}
& Nbsp; ('foo',) {}
& Nbsp; >>> s1.cancel ()
& Nbsp; Sann
Ikke noe nytt. Så nå kan du spørre: når skal jeg bruke en annen metode navn?
& Nbsp; >>> klasse Target (objekt):
& Nbsp; ... def __init __ (selv, navn):
& Nbsp; ... self.name = navn
& Nbsp; ... def _callback (selvstendig, * args, ** nøkler):
& Nbsp; ... print self.name, args, nøkler
& Nbsp; >>> s1 = some_event.subscribe (Target ('foo'))
& Nbsp; >>> some_event.publish ('! Bumm') #doctest: + ellipse
& Nbsp; Traceback (siste samtale sist):
& Nbsp; ...
& Nbsp; Feiltype: 'Mål' objektet ikke oppsigelige
Oops. La oss ta gjerningsmannen, før noen merknader våre feil:
& Nbsp; >>> s1.cancel ()
& Nbsp; Sann
& Nbsp; >>> s1 = some_event.subscribe (Target ('foo'), method = "_ tilbakeringing")
& Nbsp; >>> some_event.publish ('verker!')
& Nbsp; ('! Works',) {}
& Nbsp; foo ('verker!',) {}
Reference Retention
Så, det er det. Det er fortsatt et uutforsket argument for å abonnere igjen, men: reference_retention. Navnet høres farlig, men hva gjør det?
& Nbsp; >>> lytteren = Target ('yummy')
& Nbsp; >>> s2 = some_event.subscribe (lytteren, method = "_ tilbakeringing", reference_retention = RR.WEAK)
& Nbsp; >>> some_event.publish ('yow')
& Nbsp; ('yow',) {}
& Nbsp; foo ('yow',) {}
& Nbsp; yummy ('yow',) {}
Hm. Så langt er det ingen forskjeller. La oss gjøre en enkel endring:
& Nbsp; >>> lytteren = None
& Nbsp; >>> some_event.publish ('yow')
& Nbsp; ('yow',) {}
& Nbsp; foo ('yow',) {}
Ah. Ok. Vår yummy lytteren er borte. Hva skjedde? Vel, ved å angi en referanse oppbevaring politikk for svak, fortalte vi utgiveren, at den skal bruke en svak referanse til lytteren nettopp installert, i stedet for standard sterk referanse. Og etter at vi slapp den eneste andre kjente sterk referanse til lytteren ved å sette lytteren til Ingen ble lytteren faktisk fjernet fra forlaget. Merk, BTW., Som eksempelet ovenfor kan mislykkes med python andre enn CPython implementeringer, på grunn av særskilte regler med hensyn til søppelrydding. Prinsippet bør være gyldig, selv om det i Jython samt Ironpython, men i disse implementeringer, er det ingen garanti for at lytteren blir fjernet så snart den siste referanse til det er droppet.
Selvfølgelig, alt fungerer dette også, hvis metoden for å bli kalt er standard ett: __call__:
& Nbsp; >>> def make_listener (navn):
& Nbsp; ... def lytter (* args, ** nøkler):
& Nbsp; ... Skriv navn, args, nøkler
& Nbsp; ... retur lytteren
& Nbsp; >>> lytteren = make_listener ("svak")
& Nbsp; >>> s2 = some_event.subscribe (lytteren, reference_retention = RR.WEAK)
& Nbsp; >>> some_event.publish ('event')
& Nbsp; ("hendelsen",) {}
& Nbsp; foo ("hendelsen",) {}
& Nbsp; svak ("hendelsen",) {}
& Nbsp; >>> lytteren = None
& Nbsp; >>> some_event.publish ('event')
& Nbsp; ("hendelsen",) {}
& Nbsp; foo ("hendelsen",) {}
Det er omtrent alt som er å vite om biblioteket. Som jeg sa over: den er enkel, og kan ikke være nyttig for alle scenarioes og bruksmåter, men det gjør hva det ble skrevet til.
Feilhåndtering
Utgiver klassen er ikke ment å bli subclassed. Hvis du trenger å skreddersy atferd, bruker du politiske objekter / tilbakeringe, som sendes til konstruktøren. Akkurat nå er det en singel justerbar politikk, nemlig oppførselen til utgiveren i tilfelle, lyttere heve unntak:
& Nbsp; >>> def toobad (event):
& Nbsp; ... hvis hendelsen == 'raise':
& Nbsp; ... heve ValueError
& Nbsp; >>> s1 = some_event.subscribe (toobad)
& Nbsp; >>> some_event.publish ('ufarlige')
& Nbsp; ('ufarlige',) {}
& Nbsp; foo ('ufarlige',) {}
& Nbsp; >>> some_event.publish ('raise')
& Nbsp; Traceback (siste samtale sist):
& Nbsp; ...
& Nbsp; ValueError
Som du kan se, er standard oppførsel for å høyne unntak innenfra publisere. Dette kan ikke være tilstrekkelig, avhengig av brukstilfellet. Spesielt vil det forhindre lyttere senere registrerte som skal kjøres. Så, la oss definere vår egen feilhåndtering:
& Nbsp; >>> def log_error (unntak, verdi, traceback, tegnings, args, nøkler):
& Nbsp; ... print "fanget", unntaket
& Nbsp; >>> publisher = Publisher (exception_handler = log_error)
& Nbsp; >>> publisher.subscribe (toobad) #doctest: + ellipse
& Nbsp;
& Nbsp; >>> publisher.subscribe (skriver) #doctest: + ellipse
& Nbsp;
& Nbsp; >>> publisher.publish ('ufarlige')
& Nbsp; ('ufarlige',) {}
& Nbsp; >>> publisher.publish ('raise')
& Nbsp; fanget
& Nbsp; ('raise',) {}
Som et alternativ til å gi feilbehandleren på byggetiden, kan du også gi en feilbehandleren når du publiserer en hendelse, som så:
& Nbsp; >>> def log_error_2 (unntak, verdi, traceback, tegnings, args, nøkler):
& Nbsp; ... print "fanget", unntak, "under publikasjonen"
& Nbsp; >>> publisher.publish_safely (log_error_2, 'raise')
& Nbsp; fanget
& Nbsp; ('raise',) {}
Som du kan se, tar per-call feilbehandleren forrang over forlagets standardfeilbehandleren. Legg merke til at det ikke er kjeding, dvs. hvis per-call feilbehandleren hever et unntak, er forlagets standard handler ikke kalt, men unntaket er bare spredd utover til den som ringer på publish_safely: utgiveren har ingen måte å skille mellom Unntakene hevet fordi føreren ønsker å avbryte avsendelse og unntak hevet ved et uhell, slik at alle unntak hevet av behandleren er bare videresendt til klientprogrammet.
Thread Safety
Biblioteket er fullt tråd klar og tråd trygt. Dermed abonnere på en lytter delt på tvers av flere tråder er trygt, og så avbryter abonnement
Hva er nytt i denne utgaven.
- Abonnement håndterer nå gi tilgang til sine lytter objekter og metodenavn. Dette ble lagt på grunn av feilbehandling kode, som ønsker å logge unntak og gi en bedre måte å identifisere selve lytteren, som gikk rogue.
Hva er nytt i versjon 0.2:
- Feilhåndtering er endret. I stedet for subclassing utgiveren, blir standardunntaksbehandler nå passert som tilbakeringing til forlaget under bygging. Klassen Publisher er nå dokumentert som & quot; ikke ment for å være subclassed & quot;.
Krav
- Python
Kommentarer ikke funnet