简体   繁体   中英

Python DBusGMainLoop inside thread and try and catch block

I'm currently trying to create a python script which has to use the GObject.MainLoop() to communicate with a Bluetooth client. I put the loop in a new thread in order to not block the remaining code.

Everything works fine until I've tried to quit the program with Control + C. If I hit this command the second try and catch block ("Host:...") does not seem to get executed.

Example script:

import time
import threading

from dbus.mainloop.glib import DBusGMainLoop

try:
    from gi.repository import GObject
except ImportError:
    import gobject as GObject

DBusGMainLoop(set_as_default=True)

def myThread(a):
    try:
        GObject.threads_init()
        mainloop = GObject.MainLoop()
        mainloop.run()

    except KeyboardInterrupt:
        mainloop.quit()
        print("Thread: KeyboardInterrupt")
    return

try:
    myT = threading.Thread(target=myThread, args=(1,))
    myT.start()

    while 1:
        print("Host: Print every 1 sec")
        time.sleep(1)
except KeyboardInterrupt:
    print("Host: KeyboardInterrupt")

Output of the script:

Host: Print every 1 sec
Host: Print every 1 sec
^CHost: Print every 1 sec
Thread: KeyboardInterrupt
/usr/lib/python2.7/dist-packages/gi/types.py:113: Warning: Source ID 1 was not found when attempting to remove it
  return info.invoke(*args, **kwargs)
Host: Print every 1 sec
Host: Print every 1 sec
Host: Print every 1 sec
Host: Print every 1 sec

Process finished with exit code -1

Now I'm wondering why "print("Host: KeyboardInterrupt")" does not get executed. Furthermore I'm not sure how to solve the stated warning.

Hope you can help!

In fact I was able to solve the problem by myself.

You just have to put the MainLoop() in the main thread and start the other action which currently executes "print("Host: Print every 1 sec")" in a new thread (myT). So you have to change threads from the code above. Then if a KeyboardInterrupt happens, you have to manually exit the second thread (myT).

The reason why only "print("Thread: KeyboardInterrupt")" is called is, that if you use a MainLoop the process calling it will be seen as the "new main tread".

However, I'm still not sure how to get rid of the error:

(process:2429): GLib-CRITICAL **: Source ID 1 was not found when attempting to remove it

According to the post " GLib-CRITICAL **: Source ID XXX was not found when attempting to remove it " the warning is not a problem, so I'll just ignore it. Hope this helps anyone who'll stumble on this post!

Example:

import time
import threading

from dbus.mainloop.glib import DBusGMainLoop

try:
    from gi.repository import GObject
except ImportError:
    import gobject as GObject

DBusGMainLoop(set_as_default=True)

def myThread(run_event):
    while run_event.is_set():
        print("Thread: Print every 1 sec")
        time.sleep(1)
    print("Thread: Exit")
    return

try:
    run_event = threading.Event()
    run_event.set()

    myT = threading.Thread(target=myThread, args=(run_event,))
    myT.start()

    GObject.threads_init()
    mainloop = GObject.MainLoop()
    mainloop.run()

except (KeyboardInterrupt, SystemExit):
    mainloop.quit()
    run_event.clear()
    myT.join()
    print("Host: KeyboardInterrupt")

Output:

Thread: Print every 1 sec
Thread: Print every 1 sec
^CThread: Exit
Host: KeyboardInterrupt

(process:2429): GLib-CRITICAL **: Source ID 1 was not found when attempting to remove it

See also: Closing all threads with a keyboard interrupt

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM