Python input() call blocks other threads from printing to console - python

Thread1: Just blocks on user-input, and then adds the input to a queue before going back to blocking.
Thread2: Prints to console.
I don't see Thread2 outputs unless I enter something on the console. i.e unblock thread1. Is there a way to output to console while also blocking on input in another thread?
import threading
import time
def reader():
while(1):
text=input()
def writer():
while(1):
time.sleep(1)
print("Thread 2")
t1 = threading.Thread(target=reader)
t2 = threading.Thread(target=writer)
t1.start()
t2.start()
while(1):
#Do nothing
time.sleep(1)
Environment: Windows, WPy 3.6.7

Related

Is it the right way to run 2 infiniteloop in python?

i wrote a code in python with 2 infinite loop like this:
import threading
import time
ticker = 0
def ticking():
global ticker
while True:
time.sleep(1)
ticker +=1
print("ticker = {}".format(ticker))
def main_line():
while True:
print("Hello world")
time.sleep(4)
t1 = threading.Thread(target = ticking)
t2 = threading.Thread(target = main_line)
t1.start()
t2.start()
#t1.join()
if __name__ == "__main__":
t1.join()
#t2.join()
If i don't join any thread it's not working, but when i join 1 thread, another thread is work too but i don't know why?
Can anyone explain for me?
Join is used to block the calling method until the thread finishes, throws an exception or time out.
join([timeout]) Wait until the thread terminates. This blocks the
calling thread until the thread whose join() method is called
terminates – either normally or through an unhandled exception – or
until the optional timeout occurs.
In your case, you have started both threads. So both threads are working. But once you block the main thread by t1.join(), both running threads will be visible.
it is because you also "start" another thread. If you make a comment on t2.start(), then the thread is only working on t1.
t1.start()
# t2.start()

Run a function in a seperate python thread

(Python 3.8.3)
I am using two python threads right now, one that has a while True loop
import threading
def threadOne():
while True:
do(thing)
print('loop ended!')
t1=threading.Thread(threadOne)
t1.start()
And another that checks for a ctrl+r input. When recieved, I need the second thread to tell the first thread to break from the while loop. Is there a way to do this?
Note that I cannot change the loop to 'while Break == False' as do(thing) waits for user input, but i need this to be interrupted.
The recommended way is to use threading.event (You can combine this with event.wait if you want to sleep in that thread too however as you are waiting for a user event, probably dont need that).
import threading
e = threading.Event()
def thread_one():
while True:
if e.is_set():
break
print("do something")
print('loop ended!')
t1=threading.Thread(target=thread_one)
t1.start()
# and in other thread:
import time
time.sleep(0.0001) # just to show thread_one keeps printing
# do something for little bit and then it break
e.set()
EDIT: To interrupt the thread while it's waiting for user input you can send SIGINT to that thread and and it will raise KeyboardInterrupt which you can then handle. Unfortunate limitation of python, including python3, is that signals to all threads are handled in the main thread so you need to wait for the user input in the main thread:
import threading
import sys
import os
import signal
import time
def thread_one():
time.sleep(10)
os.kill(os.getpid(), signal.SIGINT)
t1=threading.Thread(target=thread_one)
t1.start()
while True:
try:
print("waiting: ")
sys.stdin.readline()
except KeyboardInterrupt:
break
print("loop ended")

How can I make the print() function not take the text in the input field with it

I am trying to make a console for my python applications, but i ran into a problem:
when printing something using the print() function, the text in the input field is also included. This is purely visual, because the program still works.
I tried searching online, but I do not even now what to search for and had no luck.
This is my code. It prints "foo" until the user types "exit":
import multiprocessing as mp
import os
import time
def f(q):
while True:
print(q)
time.sleep(1)
if __name__=="__main__":
p=mp.Process(target=f, args=("foo",))
p.start()
while True:
comm=str(input())
if comm=="exit":
p.terminate()
break
When the program is running, the user can still type, but when the program prints something, it also takes whatever is in the input field at the time:
foo
foo
foo
foo
efoo
xfoo
itfoo
When pressing "enter", the program still registers the input correctly and exits the program.
Here is a modification of your code that only prints foo after you have finished your input typing (i.e., until you hit Enter):
import multiprocessing as mp
from multiprocessing import Queue
def f(q, queue):
while True:
queue.get()
print(q)
if __name__=="__main__":
queue = Queue()
p=mp.Process(target=f, args=("foo", queue))
p.start()
while True:
comm=str(input())
queue.put(None)
if comm=="exit":
p.terminate()
break
If terminating the process is all you want your user to be able to do, then you can instruct them to enter Ctrl+C if they wish to stop the operation and then catch the KeyboardInterrupt exception that comes along with it.
import multiprocessing as mp
import os
import time
def f(q):
while True:
print(q)
time.sleep(1)
if __name__=="__main__":
p=mp.Process(target=f, args=("foo",))
print("Process starting. Use Ctrl+c anytime to stop it!")
p.start()
try:
while True:
input() # Trash command
except KeyboardInterrupt:
print("Terminating process...")
p.terminate()
print("Process terminated...")
If you want to do more complicated commands then a GUI would be your best approach (as mentioned by John)

Why does my multiprocess queue not appear to be thread safe?

I am building a watchdog timer that runs another Python program, and if it fails to find a check-in from any of the threads, shuts down the whole program. This is so it will, eventually, be able to take control of needed communication ports. The code for the timer is as follows:
from multiprocessing import Process, Queue
from time import sleep
from copy import deepcopy
PATH_TO_FILE = r'.\test_program.py'
WATCHDOG_TIMEOUT = 2
class Watchdog:
def __init__(self, filepath, timeout):
self.filepath = filepath
self.timeout = timeout
self.threadIdQ = Queue()
self.knownThreads = {}
def start(self):
threadIdQ = self.threadIdQ
process = Process(target = self._executeFile)
process.start()
try:
while True:
unaccountedThreads = deepcopy(self.knownThreads)
# Empty queue since last wake. Add new thread IDs to knownThreads, and account for all known thread IDs
# in queue
while not threadIdQ.empty():
threadId = threadIdQ.get()
if threadId in self.knownThreads:
unaccountedThreads.pop(threadId, None)
else:
print('New threadId < {} > discovered'.format(threadId))
self.knownThreads[threadId] = False
# If there is a known thread that is unaccounted for, then it has either hung or crashed.
# Shut everything down.
if len(unaccountedThreads) > 0:
print('The following threads are unaccounted for:\n')
for threadId in unaccountedThreads:
print(threadId)
print('\nShutting down!!!')
break
else:
print('No unaccounted threads...')
sleep(self.timeout)
# Account for any exceptions thrown in the watchdog timer itself
except:
process.terminate()
raise
process.terminate()
def _executeFile(self):
with open(self.filepath, 'r') as f:
exec(f.read(), {'wdQueue' : self.threadIdQ})
if __name__ == '__main__':
wd = Watchdog(PATH_TO_FILE, WATCHDOG_TIMEOUT)
wd.start()
I also have a small program to test the watchdog functionality
from time import sleep
from threading import Thread
from queue import SimpleQueue
Q_TO_Q_DELAY = 0.013
class QToQ:
def __init__(self, processQueue, threadQueue):
self.processQueue = processQueue
self.threadQueue = threadQueue
Thread(name='queueToQueue', target=self._run).start()
def _run(self):
pQ = self.processQueue
tQ = self.threadQueue
while True:
while not tQ.empty():
sleep(Q_TO_Q_DELAY)
pQ.put(tQ.get())
def fastThread(q):
while True:
print('Fast thread, checking in!')
q.put('fastID')
sleep(0.5)
def slowThread(q):
while True:
print('Slow thread, checking in...')
q.put('slowID')
sleep(1.5)
def hangThread(q):
print('Hanging thread, checked in')
q.put('hangID')
while True:
pass
print('Hello! I am a program that spawns threads!\n\n')
threadQ = SimpleQueue()
Thread(name='fastThread', target=fastThread, args=(threadQ,)).start()
Thread(name='slowThread', target=slowThread, args=(threadQ,)).start()
Thread(name='hangThread', target=hangThread, args=(threadQ,)).start()
QToQ(wdQueue, threadQ)
As you can see, I need to have the threads put into a queue.Queue, while a separate object slowly feeds the output of the queue.Queue into the multiprocessing queue. If instead I have the threads put directly into the multiprocessing queue, or do not have the QToQ object sleep in between puts, the multiprocessing queue will lock up, and will appear to always be empty on the watchdog side.
Now, as the multiprocessing queue is supposed to be thread and process safe, I can only assume I have messed something up in the implementation. My solution seems to work, but also feels hacky enough that I feel I should fix it.
I am using Python 3.7.2, if it matters.
I suspect that test_program.py exits.
I changed the last few lines to this:
tq = threadQ
# tq = wdQueue # option to send messages direct to WD
t1 = Thread(name='fastThread', target=fastThread, args=(tq,))
t2 = Thread(name='slowThread', target=slowThread, args=(tq,))
t3 = Thread(name='hangThread', target=hangThread, args=(tq,))
t1.start()
t2.start()
t3.start()
QToQ(wdQueue, threadQ)
print('Joining with threads...')
t1.join()
t2.join()
t3.join()
print('test_program exit')
The calls to join() means that the test program never exits all by itself since none of the threads ever exit.
So, as is, t3 hangs and the watchdog program detects this and detects the unaccounted for thread and stops the test program.
If t3 is removed from the above program, then the other two threads are well behaved and the watchdog program allows the test program to continue indefinitely.

Python input and output threading

I want to create a python script that prints out messages from one thread, while still waiting for you to input on another. Is this possible? And if so, how?
System: Windows 7
Language: Python 2.7
I have tried this (modified from a different question):
import threading
import time
def message_loop():
while True:
time.sleep(1)
print "Hello World"
thread = threading.Thread(target = message_loop)
thread.start()
while True:
input = raw_input("Prompt> ")
But what happens is: the program waits until I have finished inputting before it outputs Hello World.
It's absolutely possible. If you have a function that prints output (let's call it print_output) you can start it up in a different thread using the threading module:
>>> import threading
>>> my_thread = threading.Thread(target=print_output)
>>> my_thread.start()
You should now start getting your output. You can then run the input bit on the main thread. You could also run it in a new thread, but there are some advantages to running input in the main thread.
This works for me.
The code prints message before you input 'q'
import threading
import time
def run_thread():
while True:
print('thread running')
time.sleep(2)
global stop_threads
if stop_threads:
break
stop_threads = False
t1 = threading.Thread(target=run_thread)
t1.start()
time.sleep(0.5)
q = ''
while q != 'q':
q = input()
stop_threads = True
t1.join()
print('finish')

Categories