Also, I think I am now starting to get a hang of things; however, one doubt solved raises another doubt :D
The reason I began looking out for the two-threads-approach, is because when trying to use the GUI (Gtk) application as a dbus-service, I was getting the error "This connection was not provided by any of .service files". I now see that the reason of it was :: I wasn't using "dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)" prior to the statement "Gtk.main()". Now, by your helpful guidance, wherein you stated that "Gtk.main()" has the same effect as "GObject.MainLoop.run()", I added the statement "dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)" before "Gtk.main()", and voila.. now I could get a proxy object, and invoke methods remotely. Thus, two threads are now not needed. However, it now raises a new doubt : in my second approach, wherein I used "add_to_signal_receiver" (at the server side), and dbus-send (at the client side), how come things worked now, since I did not add "dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)" in this approach at all? I presume that even in this case, dbus would need to know that the GUI application is ok to listen to dbus-signals? Are the different requirements in these two approaches expected? Or is it an inconsistency with dbus-python? On Tue, Dec 25, 2012 at 10:04 PM, Ajay Garg <ajaygargn...@gmail.com> wrote: > Thanks Simon. > > Thanks for the extensive info; however it needs some hours (if not days > :P) to be digested. > > On Tue, Dec 25, 2012 at 9:24 PM, Simon McVittie < > simon.mcvit...@collabora.co.uk> wrote: > >> On 24/12/12 08:26, Ajay Garg wrote: >> > For a recap of the brief history, I have a parent process, that is >> > spawning a child process via "subprocess". >> > Currently, the child-process is a GUI process; however, I intend to >> > "behave" it as a dbus-service as well. >> >> In general that is something that can work, but it's necessary to >> understand a bit about how main loops work, and how the modules of your >> process deal with a main loop. >> >> Just saying "GUI" is not very informative: there are dozens of GUI >> frameworks that you might be using, each with their own requirements and >> oddities. If you say Gtk, or Qt, or Tk, or Windows MFC, or whatever >> specific GUI framework you're using, then it becomes possible to say >> something concrete about your situation. >> >> Based on later mails in the thread you seem to be using Gtk. >> >> I should note here that you seem to be using PyGtk (the "traditional" >> Gtk 2 Python binding), which is deprecated. The modern version is to use >> PyGI, the Python GObject-Introspection binding, and Gtk 3. >> >> When using PyGI, you have a choice of two D-Bus implementations: either >> GDBus (part of gi.repository.GIO), or dbus-python ("import dbus"). I >> would recommend GDBus, since dbus-python is constrained by backwards >> compatibility with some flawed design decisions. >> >> However, assuming you're stuck with dbus-python: >> >> > I then used composition, wherein another class, "RemoteListener" >> > deriving from "dbus.service.Object" was made an attribute of the "main" >> > class. That worked. >> > However, when I do >> > >> > dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) >> > GObject.mainloop.run() >> > >> > in the "RemoteListener"'s __init__ method, the GUI of the "main" class >> > fails to load (apparently, because the "mainloop.run()" causes the >> > singular, main-thread to go into busy-wait). >> >> Almost; it's not a busy-wait. GObject.mainloop.run() is the equivalent >> of this pseudocode: >> >> def run(self): >> while not global_default_main_context.someone_has_called_quit: >> if global_default_main_context.has_more_events(): >> global_default_main_context.process_next_event() >> else: >> global_default_main_context.wait_for_an_event() >> >> so it will loop until someone calls GObject.mainloop.quit() or >> equivalent, or forever if that never happens - but as long as nothing >> "interesting" happens, it will block on a poll() or select() syscall in >> what my pseudocode calls wait_for_an_event(), which is the right thing >> to do in event-driven programming like GLib/Gtk. >> >> (If you replace the last line of my pseudocode with "continue", that >> would be a busy-wait.) >> >> > I tried option b), but now instantiating "RemoteListener" in a separate >> > thread >> >> It is unclear whether the dbus-glib main loop glue (as set up by >> DBusGMainLoop) is thread-safe or not. The safest assumption is always >> "if you don't know whether foo is thread-safe, it probably isn't". In >> any case, if it *is* thread-safe, the subset of it that's exposed >> through dbus-python isn't enough to use it in multiple threads. >> >> GDBus, as made available via PyGI (specifically, gi.repository.GIO), is >> known to be thread-safe. >> >> > Is there a way to run GUI and a dbus-service together? >> >> The general answer: only if either the GUI and the D-Bus code >> run in different threads, or if they run in the same thread and can be >> made to share a main context. >> >> The specific answer for Gtk: yes, they can easily share a main context. >> >> This: >> >> > dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) >> >> sets up dbus-python's mainloop integration to integrate with the global >> default main-context in GLib (implementation detail: it currently uses >> dbus-glib to do that). What that means is that whenever a D-Bus >> connection started by dbus-python wants to listen for events on a >> socket, or wait for a timeout, it will ask GLib to add those to the >> global default main context as event sources. >> >> This: >> >> > GObject.mainloop.run() >> >> iterates GLib's global default main context, analogous to the pseudocode >> I mentioned before. Any "interesting" events that happen will cause your >> code to be executed. >> >> A typical GUI application also needs to run the main loop to >> wait for events. In PyGtk, you'd typically do that with: >> >> > Gtk.main() >> >> Gtk also uses GLib's global default main context, so this is pretty >> similar to GObject.mainloop.run() - if you just remove the call to >> GObject.mainloop.run() and use Gtk.main() instead, everything should be >> fine. >> >> > As per http://www.pygtk.org/pygtk2reference/class- >> > gobjectmainloop.html, it seems that we must be able to add event >> > sources to gobject.mainloop >> >> Yes. For instance, gobject.timeout_add(), gobject.idle_add() and >> gobject.io_add_watch() all add event sources to the default main context. >> >> dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) tells dbus-python >> that when it needs to add an event source to "the" main loop, it should >> use equivalent C functions in GLib to do so. >> >> (In principle, DBusGMainLoop ought to take a GObject.MainContext as an >> optional argument - but that's never been implemented, and it currently >> always uses the default main context, which is the same one Gtk uses, >> and which should only be iterated from the main thread.) >> >> > Once the event sources are added, each instance of gobject.mainloop >> > (in its particular thread), will cater to only those sources. >> >> No, that's not true; gobject.mainloop is a namespace for a set of global >> functions, not an object. If you must use multiple threads (not >> recommended), please see the GLib C API documentation for details of how >> main loops and main contexts relate, then the PyGtk documentation to see >> how that translates into Python. >> >> > How is dbus."mainloop.glib.DBusGMainLoop(set_as_default=True)" >> > related to gobject.mainloop? >> >> It instantiates a new DBusGMainLoop and sets it as dbus-python's global >> default main-loop-integration object. (With hindsight, DBusGMainLoop was >> a poor choice of name - it should have been DBusGMainIntegration or >> something.) The result is that whenever a new dbus.connection.Connection >> is instantiated, it will call methods on that DBusGMainLoop to connect >> its event sources up to the default GLib main context, which is the same >> one used by Gtk. >> >> dbus.bus.BusConnection, dbus.Bus, dbus.SessionBus etc. are >> dbus.connection.Connection subclasses, so anything I say about >> dbus.connection.Connection applies equally to them. >> >> > How is dbus."mainloop.glib.DBusGMainLoop(set_as_default=False)" >> > related to gobject.mainloop? >> >> It instantiates a new DBusGMainLoop and doesn't use it for anything. If >> you save the returned DBusGMainLoop in a variable (e.g. >> my_dbus_g_main_loop = DBusGMainLoop(...)), then you can pass a keyword >> argument mainloop=my_dbus_g_main_loop to a dbus.connection.Connection >> constructor, and that dbus.connection.Connection will use that >> DBusGMainLoop instead of dbus-python's global default. In practice, only >> a very unusual application would need to do that. >> >> There is currently no point in having more than one DBusGMainLoop; it >> would become useful if dbus-glib was thread-safe, and if dbus-python >> supported non-default GLib main-contexts. >> >> > Is it necessary at all to specify >> > "mainloop.glib.DBusGMainLoop(set_as_default=True)" or >> > "mainloop.glib.DBusGMainLoop(set_as_default=False)" when using >> > gobject.mainloop? >> >> Yes. Otherwise, dbus-python has no way to know that your application is >> going to be iterating the GLib main loop, as opposed to Qt or Tk or >> Enlightenment or something. >> >> > currently for the client, I am having the (client) (parent) process >> > run the command "dbus-send" via the python-subprocess API. >> > Does there exist a python API to do it in a cleaner manner? >> >> Yes, either dbus-python or GDBus. Each of those can do everything >> dbus-send can, and more. >> > > For a start, could you please point me to the paradigm to send a > dbus-signal from the client to the server (where the server has the > "add_to_signal_receiver" been set up). > > From the limited googling that I did, I remember someone saying that for > sending a signal, the typical setting-up-of-a-proxy-object is not required; > however, I could not hit upon the exact dbus-python mechanism to send a > signal :-\ > > > >> >> S >> _______________________________________________ >> dbus mailing list >> d...@lists.freedesktop.org >> http://lists.freedesktop.org/mailman/listinfo/dbus >> > > > > -- > Regards, > Ajay > -- Regards, Ajay
_______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com