Pas­si­ve wai­ting is a way of suspen­ding pro­grams execu­ti­on without con­su­ming any CPU (in con­trast with acti­ve wai­ting whe­re a pro­gram is busy doing nothing). In Python, you can use cer­ta­in clas­ses from the threa­ding modu­le (such as Con­di­ti­on and Event). Let’s take for exam­ple the Event class. It is good for wai­ting for an event. But what if you need to wait for many events? You might say „Why not to make a list of mul­tiple Event objects and wait for all of them?” Well… that is not going to work:

The­re are two pro­blems with this kind of code:

  • If you use any time­out value, you degra­de it to acti­ve wait (and you will also wait until the last event in the list gets acti­va­ted or times out).
  • If you don’t use a time­out value, the code gets stuck on the first event (and then the second, thi­rd, etc.).

If you used to pro­gram in C/C++, you might want to use a select functi­on. Select allows you to wait for seve­ral I/O ope­rati­ons and returns when any of them ends. The good news is the­re is such a functi­on in Python 3. Con­cre­te­ly, it is the select method of the selectors.BaseSelector class. The bad news is you can wait only on file objects.

I don’t know how about you but I’d like to wait on other things, such as MULTIPLE EVENT OBJECTS! But you can’t, because tho­se are not file objects. Now you might be say­ing

“I wish the­re was a way to wait on tho­se blo­o­dy Event objects.”

Well… the­re is :-). Here’s a sli­ght­ly modi­fied code, so it works in Python 3 (ori­gin is here):

To wait for mul­tiple event objects using the select method is sim­ple as this:

Any sug­ges­ti­ons or impro­ve­ments? Lea­ve a com­ment below :-).


Alexander Mohr · 2018-04-24 at 23:31

How about Sema­pho­re?

Eberto · 2018-10-19 at 17:07

With this, I am able to wait for a time­out sha­red between events. If one times out, the next ones will wait 0 seconds.

events=[threading.Event() for _ in range(10)] # make 10 events
collections.deque((e.clear() for e in events), 0) # clear all event flags

target_time = time.time() + timeout_seconds
activated={e for e in events if e.wait(max(target_time – time.time(), 0))} # wait for events, get a set of acti­va­ted ones

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.