Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python Threading and Subprocesses

so I'm having a problem with threading. I have included an example similar to the one I am encountering in my program. When I run the following code, it will only print "hello" after the "Quit" button in the menu has been pressed. It seems to hang on the subprocess.call(). I don't understand what's going wrong!

Also, I have no experience with threading in Python and I'm new to the language as a whole, so feel free to yell at me for structural flaws, as well as Python programming conventions! :)

Thanks!

import threading
import subprocess

import gtk

class TestDaemon:
    def __init__(self):

        # start thread here
        cmdman = CommandManager()
        threading.Thread(target=cmdman.run, args=('CmdThread', 1)).start()

        self.icon = gtk.StatusIcon()
        self.icon.set_from_stock(gtk.STOCK_ABOUT)
        self.icon.set_visible(True)

        self.menu = gtk.Menu()
        self.menu_item = gtk.ImageMenuItem(gtk.STOCK_QUIT)
        self.menu_item.connect('activate', self.quit_app, self.menu)
        self.menu.append(self.menu_item)

        self.icon.connect('popup-menu', self.popup_menu, self.menu)
        self.icon.set_visible(True)

        gtk.main()

    def quit_app(self, widget, data = None):
        gtk.main_quit()

    def popup_menu(self, widget, button, time, data = None):
        if button == 3 and data:
            data.show_all()
            data.popup(None, None, gtk.status_icon_position_menu,
                       3, time, self.icon)

class CommandManager:
    def __init__(self):
        pass

    def run(self, *args):
        subprocess.call('echo "hello"', shell=True)

if __name__ == '__main__':
    TestDaemon()

EDIT: I forgot to mention, if I add a sys.stdout.write() before the subprocess.call(), the sys.stdout.write() will run, but the subprocess.call() will not.

like image 537
kotakotakota Avatar asked Jan 20 '26 12:01

kotakotakota


1 Answers

(posted as a comment initially):

join the thread before quitting:

class TestDaemon:
    def __init__(self):

        # start thread here
        cmdman = CommandManager()
        self.cmdThread = threading.Thread(target=cmdman.run, args=('CmdThread', 1))
        self.cmdThread.daemon = True
        self.cmdThread.start()

        ...

    def quit_app(self, widget, data = None):
        self.cmdThread.join()
        gtk.main_quit()

setting the thread to daemon is for the case that the main thread raises some exception and the join() is not called.

like image 99
Not_a_Golfer Avatar answered Jan 22 '26 03:01

Not_a_Golfer