Event-driven programs are very different from the Python applications that we have got so used to writing within the confines of the previous chapters of this book. Typically, each of these prior programs follows a set flow, and while some sections of a program may be nondeterministic in terms of execue main memory, and independentram very much follows a deterministic approach:
With event-driven programs, we typically have an event loop that constantly listens for incoming events. Once this event loop is started, it's entirely down to the events inputted into the system that determine what is then executed and what order they have to be executed in. An example of this would be an event-driven program that listens to keyboard input: we have no way of determining what key will be pressed next, but we will have a certain function mapped to the said key when our program receives this key-press event.
In the following diagram, you'll see an example of the flow that an event-driven program typically follows. We see it start up and then enter a Wait state. This wait state goes on indefinitely until the program is shut down through either the triggering of a specific event or a system crash.
During this Wait state, we are constantly listening for events and then passing them off to event handlers. Now, while this diagram only shows one particular event mapped to one handler, it should be noted that in some event-driven programs, the number of events and handlers could be theoretically infinite:
This makes it somewhat ideal for systems such as OS. If we had to write an OS in a procedural manner, then you would typically see an incredibly hard to follow code base that resembles an Italian specialty in the form of spaghetti code as opposed to a well-designed system.
By leveraging an event-driven paradigm for our systems, we greatly simplify our overall program's structure and make it easier to increase its functionality or debug any issues in the future.