alex
alex

Reputation: 152

Threading issue in Python 2.7

import time
import thread
import termios
import sys
import datetime


try:
    from msvcrt import getch  # try to import Windows version
except ImportError:
    def getch():   # define non-Windows version
        import tty, termios
        fd = sys.stdin.fileno()
        old_settings = termios.tcgetattr(fd)
        try:
            tty.setraw(sys.stdin.fileno())
            ch = sys.stdin.read(1)
        finally:
            termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
        return ch

def tm():

    char = None

    def keypress():
        count=0
        while count<5:
            a=time.time()
            global char
            char = getch()
            b=time.time()
            c=b-a       
            c=c*10000000000000000
            c=int (c)       
            c=c%1000            
            print c
            count+=1



    thread.start_new_thread(keypress, ())

    while True:
        '''if char is not None:
            print("Key pressed is " + char.decode('utf-8'))
            break'''
        print("Program is running")
        time.sleep(5)

thread.start_new_thread(tm ())  

when I run the code as shown above, it happily does what it's meant to do, which is measure the time in between keystrokes and give the 3 least significant numbers in the measurement.

However, when I take out this part (because I don't need nor necessarily want it there):

while True:
        '''if char is not None:
            print("Key pressed is " + char.decode('utf-8'))
            break'''
        print("Program is running")
        time.sleep(5)

It breaks. I get the following error code:

Traceback (most recent call last):
  File "randgen.py", line 50, in <module>
    thread.start_new_thread(tm ())
TypeError: start_new_thread expected at least 2 arguments, got 1

Update

when I add a comma to the thread.start_new_thread(tm, ()) I get this error:

Unhandled exception in thread started by sys.excepthook is missing lost sys.stderr However, when the comma is missing, it runs fine as long as that piece of while True code is there.

Upvotes: 2

Views: 2538

Answers (3)

JaeMann Yeh
JaeMann Yeh

Reputation: 373

If you are still using Python 2.7, here is another example.

import thread
import threading

class PeriodicThread(threading._Timer):
    def __init__(self, *args, **kwargs):
        threading._Timer.__init__(self, *args, **kwargs)
        self.daemon = True

    def run(self):
        while True:
            self.finished.clear()
            self.finished.wait(self.interval)
            if not self.finished.isSet():
                self.function(*self.args, **self.kwargs)
            else:
                return
            self.finished.set()

class PeriodicThreadManager(object):
    periodic_threads = []
    def run(self, interval, callback_fn, args=[], kwargs={}):
        new_thread = PeriodicThread(interval, callback_fn, args, kwargs)
        self.periodic_threads.append(new_thread)
        thread.start_new_thread(new_thread.run, ())

    def stop_all(self):
        for t in self.periodic_threads:
            t.cancel()
        self._event.set()
    
class YourApplication:
    def __init__(self):
        self.threads = PeriodicThreadManager()
        self.threads.run( .01, self.periodic_callback_1 ) # 10 ms but ...
        self.threads.run( .01, self.periodic_callback_2 )

    def periodic_callback_1(self):
        ....

    def periodic_callback_2(self):
        ....

Upvotes: 0

foslock
foslock

Reputation: 3939

Separate Thread

If you truly intend to run tm in a separate thread, you are missing a comma between your two positional arguments. It should read as follows:

thread.start_new_thread(tm, ())

Main Thread

If you do not need the execution of tm to happen in another thread, simple call the function in the current thread like so:

tm()

This is happening already without the comma since the space is removed by the Python interpreter.

thread.start_new_thread(tm ())
# gets turned into
thread.start_new_thread(tm())
# which evaluates tm() before calling 'start_new_thread'

If the loop is removed, the return value of tm() gets passed as a single argument to start_new_thread which results in the original error posted.

Threading

As mentioned in the other answer, you likely should be using the threading library instead of thread. More details about why are listed here.

Upvotes: 2

calico_
calico_

Reputation: 1221

You should be using threading instead of thread The thread module is a low-level interface to starting threads, and it's going to require a lot of unnecessary headaches while you're learning this. See this post

Then, the proper way to start a thread would be

import threading
import time

def printstuff(stuff):
    while 1:
        print(stuff)
        time.sleep(3)

t = threading.Thread(target=printstuff, args=('helloworld',))
t.start()

# Here is where your main thread will do whatever
print('Main thread running')
time.sleep(5)
print('Main thread done')

# At this point the main thread will be done
# but printstuff will still be printing stuff. 
# Control-c will exit the second thread, and 
# youll be back at a prompt

Your code above is not a minimal example, and it's very hard to understand what you're actually trying to accomplish. Try clarifying the goal in some pseudo-code, and then I can work with you to improve your understanding of multi-threading.

Upvotes: 4

Related Questions