6

I have a Python program and when I exit the application with Ctrl-c, the script does not close. My process still shows in running processes.

#!/usr/bin/env python
import socket
import threading
import Queue
import serial
import mysql.connector
from datetime import datetime, date, time


host = '0.0.0.0'
port = 1024
buffer = 102400
my_queue = Queue.Queue()

class readFromUDPSocket(threading.Thread):

    def __init__(self, my_queue): 
        threading.Thread.__init__(self)
        self.my_queue = my_queue

    def run(self):
        while True:
            buffer1,addr = socketUDP.recvfrom(buffer)
            self.my_queue.put(buffer1)
            print 'UDP received'

class readFromSerial(threading.Thread):

    def __init__(self, my_queue): 
        threading.Thread.__init__(self)
        self.my_queue = my_queue


    def run(self):
        while True:
            buffer2 =  ser.readline(eol=';')
            if buffer2:
                self.my_queue.put(buffer2)
                print 'Serial received'

class process(threading.Thread):

    def __init__(self, my_queue):
        threading.Thread.__init__(self)
        self.my_queue = my_queue
        self.alive = threading.Event()
        self.alive.set()

    def run(self):
        while True: 
            buffer3 = self.my_queue.get()
            today = datetime.now()
            timestamp = today.strftime("%A, %B %d, %Y %H:%M:%S")
            print 'Data pushed at:', timestamp
            print buffer3
            if buffer3.startswith('temp:'):
                temp = buffer3.replace('temp:','')
                cnx = mysql.connector.connect(user='root', password='xxxxx', database='temperature')
                cursor = cnx.cursor()
                cursor.execute("INSERT INTO temperature.temperature (time,temperature) VALUES (%s, %s)", [timestamp, temp])
                print 'Data inserted into Database'
                cnx.commit()
                cursor.close()
                cnx.close()


if __name__ == '__main__':

    # Create socket (IPv4 protocol, datagram (UDP)) and bind to address
    socketUDP = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    socketUDP.bind((host, port))
    ser = serial.Serial('/dev/ttyUSB0', 57600, timeout=2)


    # Instantiate & start threads
    myServer = readFromUDPSocket(my_queue)
    mySerial = readFromSerial(my_queue)
    myDisplay = process(my_queue)

    myServer.start()
    myDisplay.start()
    mySerial.start()

while 1:
    pass

UDPSock.close()
ser.close()

Why does the python thread not close with Ctrl+c?

Eric Leschinski
  • 146,994
  • 96
  • 417
  • 335
Ossama
  • 2,401
  • 7
  • 46
  • 83

3 Answers3

8

You need to make the thread a daemon thread. To do this add the following line after you call the Thread's init

self.setDaemon(True)

A program will exit when only daemon threads are left alive, the main thread is non-daemonic of course

GP89
  • 6,600
  • 4
  • 36
  • 64
  • 2
    Incorrect summary. If you spawn a daemon thread X and a non-daemon thread Y and exit the main thread M, the daemon thread X will *not* die. -- "A daemon thread will not prevent the program from exiting" is a more correct phrasing. – Deestan Sep 19 '12 at 11:14
  • 2
    You're right, thanks! I've edited my answer- my understanding was off – GP89 Sep 19 '12 at 11:15
  • 4
    The preferred spelling is `self.daemon = True` – Steven Rumbalski Sep 19 '12 at 11:37
  • @Steven Surely self.setDaemon is preferable. If you spell .setDaemon wrong, you get an obvious `AttributeError`, if you spell `self.daemon` wrong, you get no error and a non-daemonised thread that you think is daemonised, and some unwanted bugs – GP89 Sep 19 '12 at 13:33
  • 1
    @GP89: You make a valid point. However, the 2.7 docs [describe](http://docs.python.org/library/threading.html#threading.Thread.setDaemon) `setDaemon` as "Old API for daemon". The 3.3 docs [say](http://docs.python.org/dev/library/threading.html#threading.Thread.setDaemon) "Old getter/setter API for daemon; use it directly as a property instead." So when I say that using it as a property is preferred, I'm paraphrasing the docs. – Steven Rumbalski Sep 19 '12 at 13:43
  • this was what i did:class readFromSerial(threading.Thread): def __init__(self, my_queue): threading.Thread.__init__(self) self.setDaemon(True) self.my_queue = my_queue – Ossama Oct 06 '12 at 06:25
3

the_thread.setDaemon(true), see http://docs.python.org/library/threading.html#threading.Thread.daemon

Marcus
  • 6,701
  • 4
  • 19
  • 28
0

I was unable to kill my python sub process because I had set the shell=True option in the process.Popen command. I removed shell=True and then I could kill it.

If the subprocess is a shell, then you will have to kill the things it is running before the shell will end itself.

Eric Leschinski
  • 146,994
  • 96
  • 417
  • 335