Haciendo una aplicación única con python y DBUS
Lo busqué en google y siempre encuentro la misma respuesta, "usá dbus, tratá de tomar el nombre, si ya existe, entonces hay una copia corriendo".
Lo que no pude encontrar es un ejemplo que funcione de esto, o al menos no un ejemplo convenientemente etiquetado "así es como se hace una aplicación única usando DBUS y python".
Así que, así es como se hace una aplicación única usando DBUS y python:
Suponiendo que tu aplicación se llama uRSSus (la mía se llama así):
session_bus = dbus.SessionBus() try: session_bus.get_object("org.urssus.service", "/uRSSus") # Esta es la segunda copia, hacer que se vea la primera # TODO: implementar except dbus.DBusException: # No hay otra copia corriendo # Esto 'toma' el nombre DBUS name = dbus.service.BusName("org.urssus.service", bus=session_bus) # Ahora, empezá la aplicación: window=MainWindow() object = UrssusServer(window,name) : : : etc, etc
Y eso es todo. No, no es difícil, pero como la documentación de DBUS es... o mejor dicho como la documentación de DBUS no es, cada cosita puede ayudar.
For our office app I have used Shared Memory. Your approach is educative too :)
Thanks :-)
There is a tiny race condition, though, but I am not sure I care about it ;-)
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.
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.
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.
@Tom
But... constructing BusName doesn't fail.
@Tom
But... constructing BusName doesn't fail.
Excelente amigo!!!