Skip to main content

Ralsina.Me — Roberto Alsina's website

Making a unique application using python and DBUS

No, not unique in the sense "o­h, this app is a spe­cial snowflake", but unique in the sense "y­ou can on­ly run one copy of this ap­pli­ca­tion".

I tried googling for it and I al­ways found the same an­swer, "use dbus, try to own the name, if it ex­ists al­ready, then a copy is al­ready run­ning".

What I could not find is one work­ing ex­am­ple of this, or at least not some­thing con­ve­nient­ly la­beled "here is how you do a unique ap­pli­ca­tion us­ing dbus and python".

So, here is how you do a unique ap­pli­ca­tion us­ing dbus and python:

Sup­pos­ing your ap­pli­ca­tion is called uRSSus (mine is):

session_bus = dbus.SessionBus()
try:
    session_bus.get_object("org.urssus.service", "/uRSSus")
    # This is the second copy, make the first one show instead
    # TODO: implement
except dbus.DBusException: # No other copy running
    # This will 'take' the DBUS name
    name = dbus.service.BusName("org.urssus.service", bus=session_bus)
    # Now, start your app:
    window=MainWindow()
    object = UrssusServer(window,name)
    :
    :
    :
    etc, etc

And that's it. No, it's not hard, but since the DBUS docs seem to be... rather they seem al­most not to be some­times, ev­ery lit­tle bit may help.

Ankur / 2009-12-11 16:16:

For our office app I have used Shared Memory. Your approach is educative too :)

Roberto Alsina / 2009-12-11 16:29:

Thanks :-)

There is a tiny race condition, though, but I am not sure I care about it ;-)

Ed Page / 2009-12-11 18:32:

I was just thinking about the race myself.

Approach 1 Get Object and if fails Create Object and Launch

This has a race of an app launching between the failed get and the create

Approach 2 Create Object and Launch and if fails get object

This has a race when the app closes between the failed create and the get.

I think this isn't satisfactory of enforcing uniqueness but handling what to do when another instance is launched but maybe for your use case one of the races is acceptable. I would guess file locks, which active state's python cookbook has some examples of (some with races, some without) would be better for enforcing uniqueness.

Roberto Alsina / 2009-12-11 19:03:

Well, I timed the race window.
In my slowest computer it's about 0.3 msec.

Since starting two copies of the app is not catastrophic, I can live with that, even if (of course) it's not ideal.

Tom Lynn / 2009-12-14 12:20:

You should do the "approach 2", i.e. just construct BusName(name, bus=session_bus) in the try...except without the get_object call. That's a standard Python idiom ("It's easier to ask forgiveness than permission", aka EAFP), and for good reason - it's simple and robust.

Roberto Alsina / 2009-12-16 20:41:

@Tom

But... constructing BusName doesn't fail.

Roberto Alsina / 2009-12-16 20:41:

@Tom

But... constructing BusName doesn't fail.

jonisar / 2012-05-11 23:11:

Excelente amigo!!!


Contents © 2000-2023 Roberto Alsina