We take a look at how to use the publish-subscribe pattern in Python with the help of the PyPubSub or PyDispatcher packages.
The Publish-Subscribe pattern is pretty common in computer science and very useful too. The wxPython GUI toolkit has had an implementation of it for a very long time in wx.lib.pubsub. This implementation is based on the PyPubSub package. While you could always download PyPubSub and use it directly instead, it was nice to be able to just run wxPython without an additional dependency.
However, as of wxPython 4.0.4, wx.lib.pubsub is now deprecated and will be removed in a future version of wxPython. So now you will need to download PyPubSub or PyDispatcher if you want to use the Publish-Subscribe pattern easily in wxPython.
You can install PyPubSub using pip.
Here’s how to do it:
pip install pypubsub
PyPubSub should install quite quickly. Once it’s done, let’s find out how to use it!
Let’s take an example from my previous article on this topic and update it for using PyPubSub instead:
import wx from pubsub import pubclass OtherFrame(wx.Frame):
“”“”“”def __init__(self): """Constructor""" super().__init__(None, title="Secondary Frame") panel = wx.Panel(self) msg = "Enter a Message to send to the main frame" instructions = wx.StaticText(panel, label=msg) self.msg_txt = wx.TextCtrl(panel, value="") close_btn = wx.Button(panel, label="Send and Close") close_btn.Bind(wx.EVT_BUTTON, self.on_send_and_slose) sizer = wx.BoxSizer(wx.VERTICAL) flags = wx.ALL|wx.CENTER sizer.Add(instructions, 0, flags, 5) sizer.Add(self.msg_txt, 0, flags, 5) sizer.Add(close_btn, 0, flags, 5) panel.SetSizer(sizer) def on_send_and_slose(self, event): """ Send a message and close frame """ msg = self.msg_txt.GetValue() pub.sendMessage("panel_listener", message=msg) pub.sendMessage("panel_listener", message="test2", arg2="2nd argument!") self.Close()
class MyPanel(wx.Panel):
“”“”“”def __init__(self, parent): """Constructor""" super().__init__(parent) pub.subscribe(self.my_listener, "panel_listener") btn = wx.Button(self, label="Open Frame") btn.Bind(wx.EVT_BUTTON, self.on_open_frame) def my_listener(self, message, arg2=None): """ Listener function """ print(f"Received the following message: {message}") if arg2: print(f"Received another arguments: {arg2}") def on_open_frame(self, event): """ Opens secondary frame """ frame = OtherFrame() frame.Show()
class MyFrame(wx.Frame):
“”“”“”def __init__(self): """Constructor""" wx.Frame.__init__(self, None, title="New PubSub API Tutorial") panel = MyPanel(self) self.Show()
if name == “main”:
app = wx.App(False)
The main difference here between using the built-in PubSub is the import.
All you need to do is replace this:
from wx.lib.pubsub import pub
with this:
from pubsub import pub
As long as you are using wxPython 2.9 or greater that is. If you were stuck using wxPython 2.8, then you will probably want to check out one of my previous articles on this topic to see how the PubSub API changed.
If you are using wxPython 2.9 or greater, then the change is super easy and almost painless.
As usual, you subscribe to a topic:
pub.subscribe(self.myListener, “panelListener”)
And then you publish to that topic:
pub.sendMessage(“panelListener”, message=msg)
Give it a try and see how easy it is to add to your own code!
I personally really liked using wx.lib.pubsub, so I will probably keep using it with PyPubSub. However, if you’ve ever wanted to try another package, like PyDispatcher, this would be as good a time as any to do so.
Originally published by Mike Driscoll at https://dzone.com
☞ Complete Python Bootcamp: Go from zero to hero in Python 3
☞ Learn Python by Building a Blockchain & Cryptocurrency
☞ Python and Django Full Stack Web Developer Bootcamp
☞ The Python Bible™ | Everything You Need to Program in Python
☞ Learning Python for Data Analysis and Visualization
☞ Python for Financial Analysis and Algorithmic Trading
☞ The Modern Python 3 Bootcamp
#python