So I wanted to make my own Omegle interface in Python to get some practice with the language, and also it just sounded like fun. In order to handle the inputs and outputs at the same time, I've decided to use multithreading. This is my first time working with multithreading, so I don't really know what I am doing. Whenever I try and use input() while in a multithreaded function, it returns an EOF error. Any idea how to get around it, or if I'm going about this the entirely wrong way, what is a better way to do this?
Code:
from python_omegle import InterestsChat
from python_omegle import ChatEvent
from multiprocessing import Process
import sys
def start_chat_loop():
interests = input("Please input interests: ").split
chat = InterestsChat(interests)
chat_loop(chat=chat)
p2 = Process(target = take_input)
p2.start()
def take_input():
while True:
i = input()
if(i == "/next"):
chat.disconnect()
else:
print("You: typing...")
chat.send(i)
print("You: "+i)
def chat_loop(chat):
while True:
# Start a new chat every time the old one ends
print("- Starting chat -")
chat.start()
while True:
event, argument = chat.get_event()
if event == ChatEvent.CHAT_WAITING:
print("- Waiting for a partner -")
elif event == ChatEvent.CHAT_READY:
common_interests = argument
print("- Connected, common interests: {} -".format(*common_interests))
break
# Connected to a partner
while True:
event, argument = chat.get_event()
if event == ChatEvent.GOT_SERVER_NOTICE:
notice = argument
print("- Server notice: {} -".format(notice))
elif event == ChatEvent.PARTNER_STARTED_TYPING:
print("- Partner started typing -")
elif event == ChatEvent.PARTNER_STOPPED_TYPING:
print("- Partner stopped typing -")
elif event == ChatEvent.GOT_MESSAGE:
message = argument
print("Partner: {}".format(message))
elif event == ChatEvent.CHAT_ENDED:
print("- Chat ended -")
break
if __name__ == "__main__":
p1 = Process(target = start_chat_loop)
p1.start()
Problem spots:
def start_chat_loop():
interests = input("Please input interests: ").split
chat = InterestsChat(interests)
chat_loop(chat=chat)
p2 = Process(target = take_input)
p2.start()
def take_input():
m = False
while True:
i = input()
if(i == "/next"):
chat.disconnect()
else:
print("You: typing...")
caht.send(i)
print("You: "+i)
Does your chat.disconnect() method have a way of escaping an endless loop? I'm not too advanced with this but I believe you should either do:
if(i == "/next"):
chat.disconnect()
break
or
def take_input():
m = False
while not m:
i = input()
if(i == "/next"):
chat.disconnect()
m = True
else:
print("You: typing...")
chat.send(i)
print("You: "+i)
I also noticed in the 2nd block of code that its written:
caht.send(i) instead of chat.send(i). A syntax error might be preventing the loop of ending as well thus resulting in EOF.
Related
My code
import time
answer = None
def check():
#Global Variable Definitions
global outOfTime
global answer
#Variable Fixup
outOfTime = 2
timevalue = 0
#Set Time Dependant On Level
if difficulty == "EASY":
timevalue = 300 / level
elif difficulty == "MEDIUM":
timevalue = 150 / level
elif difficulty == "HARD":
timevalue = 5 / level
else:
print("ERROR!")
time.sleep(2) #Incase Of No Difficulty
quizStartup()
print("You Have", round(timevalue), "Seconds")
time.sleep(timevalue) #Timer
if answer == None:
outOfTime = 1
from threading import Thread
t = Thread(target = check).start
answer = input("Answer: ")
When I run this code, its being working forever but now the thread is not accessed by pylance. Any ideas on how to fix this?
Also is there anyway to stop this thread later on?
.start is not a property, you need to call it like a function, t = Thread(target=).start()
to stop a thread, the proper way is with flags
I want to produce an endless loop that would to different things depending on some user input.
When the .py is executed the loop starts and does some 'main' programm and the input window opens for the user. When typing 'alt1' the loop jumps in to the function 'main_alt1' and so on.
user_input = 'main'
user_input = input()
while True:
if user_input == 'main'
main()
elif user_input == 'alt1'
main_alt1()
elif user_input == 'exit'
exit()
The problem here is that the input is either given once before the loop (like in the example) or it stops the loop when the input is inside the loop until the input is given.
Does anyone has a smart way to do something like that. It doesn't need to be with input().
I think it's better to use a class to process the user input:
(I updated the code with the process method)
from multiprocessing import Process
from time import sleep
class InvalidAction(Exception):
pass
class Cmd:
def __init__(self):
self._active_thread = None
def _action_hi(self):
while True:
print('Hi!')
sleep(1)
def _action_ping(self):
while True:
print('Pong!')
sleep(1)
#staticmethod
def _get_method_name(action):
return f'_action_{action}'
def process(self, action: str):
method_name = self._get_method_name(action)
if not hasattr(self, method_name):
raise InvalidAction
if self._active_thread is not None:
self._active_thread.terminate()
self._active_thread = Process(target = getattr(self, method_name, None))
self._active_thread.start()
def main():
cmd = Cmd()
while True:
try:
user_input = input('Action: ')
cmd.process(user_input)
except InvalidAction as e:
print(f'Invalid Action!')
except KeyboardInterrupt:
print('Exiting the loop.')
break
except Exception as e:
print(f'Something went wrong - {e}')
if __name__ == '__main__':
main()
user_input = 'main'
user_input = input()
while True:
if user_input == 'main'
main()
elif user_input == 'alt1'
main_alt1()
elif user_input == 'exit'
exit()
user_input = input()
Taking the the input again at the end of loop works. Since it is while True it runs infinitely till user enters exit
after calling every function you can again take update from user to change variable
import keyboard
while True:
if keyboard.read_key() == 'a':
main_alt1()
elif keyboard.read_key() == 'b':
main_alt2()
elif keyboard.read_key() == 'e':
exit()
else:
main()
Little context: I'm working with a Zumi (physical toy car that can be programmed with Python)
However, this issue pertains to threading, looping, and inputs. All my threading works fine. However, a specific while loop acts weirdly after the first iteration.
from zumi.zumi import Zumi
import threading, time, sys
zumi = Zumi()
def commands(star):
global comm
print("thread 1 started")
time.sleep(1)
while star == "t":
try:
inp = str(input("Command: ")) <---
if inp.lower() == "d":
comm = "d"
elif inp.lower() == "r":
comm = "r"
elif inp.lower() == "p":
comm = "p"
elif inp.lower() == "b":
print("Killing Zumi")
zumi.stop()
sys.exit()
else:
print("I don't understand.")
except EOFError as e:
print(end = "")
inp = ""
def constacheck(star):
global comm
print("thread 2 started")
while star == "t":
if comm == "d":
forwards()
elif comm == "r":
backwards()
elif comm == "p":
parallel()
star = "t"
inp = ""
comm = ""
print("create and start thread 1")
x = threading.Thread(target=commands, args=(star))
x.start()
time.sleep(1)
print("create and start thread 2")
z = threading.Thread(target=constacheck, args=(star))
z.start()
I put an arrow which points to the area of interest. The first time I run the code, I am asked for the input, and it does everything correctly. However, immediately afterwards, it should ask for the same input, and change the variables according (which will them affect my second loop- constacheck). Instead it returns an EOFError: Error when reading a line, which I solved by making the code repeat the loop, ignoring the error. However, every loop afterwards raises the same error, and thus creates a constant loop of printing "Command: "
It looks something like this:
Command: d
Driving forwards.
Command: Command: Command: Command: Command: Command: Driving forward.Command: Command: Command: Command: Command: Command: Command: Driving forward.
etc.
How do I stop the EOFError, and every time the while loop in commands() loops, ask for an input?
Thanks.
I'm trying to design a control interface for my system which sends and receives some data through serial link. My searches related to GUI design took me to understand the "multi-threading" issue and code below shows the latest position I arrived.
This indicates similar parts (e.g try, run) with the ones I've seen on example GUIs. I planned to convert this to a GUI, once I understand how it exactly works.
So the problem is after I start, stop the code below I can't restart it again. Because, as I understand, multi-threading features only one cycle: start, stop and quit. I mean it doesn't accept start command after stop.
My question is how I can make this code to accept start after stopping?
Best wishes
import threading, random, time
class process(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
self.leave = 0
print("\n it's running ...\n\n")
while self.leave != 1:
print "Done!"
time.sleep(1)
operate = process()
while True:
inputt = input(" START : 1 \n STOP\t : 0 \n QUIT\t : 2 \n")
try:
if int(inputt) == 1:
operate.start()
elif int(inputt) == 0:
operate.leave = 1
elif int(inputt) == 2:
break
except:
print(" Wrong input, try egain...\n")
Create process inside while True loop
if int(inputt) == 1:
operate = process()
operate.start()
It should work.
... but your code may need other changes to make it safer - you will have to check if process exists before you try to stop it. You could use operate = None to control it.
import threading
import random
import time
class Process(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
self.leave = False
print("\n it's running ...\n\n")
while self.leave == False:
print("Done!")
time.sleep(1)
operate = None
while True:
inputt = input(" START : 1 \n STOP\t : 0 \n QUIT\t : 2 \n")
try:
if int(inputt) == 1:
if operate is None:
operate = Process()
operate.start()
elif int(inputt) == 0:
if operate is not None:
operate.leave = True
operate.join() # wait on process end
operate = None
elif int(inputt) == 2:
if operate is not None:
operate.leave = True
operate.join() # wait on process end
break
except:
print(" Wrong input, try egain...\n")
Other method is not to leave run() when you set leave = True but keep running thead. You would need two loops.
def run(self):
self.leave = False
self.stoped = False
print("\n it's running ...\n\n")
while self.leave == False:
while self.stoped == False:
print("Done!")
time.sleep(1)
How can I run a timer while asking for user input from the console? I was reading about multiprocessing, and I tried to use this answer: Python: Executing multiple functions simultaneously. When I tried to get it going, it gave me a bunch of framework errors.
Right now it runs start_timer(), but then stops it when it runs cut_wire().
Here's my start_timer function:
def start_timer():
global timer
timer = 10
while timer > 0:
time.sleep(1)
timer -= 1
sys.stdout.write ("There's only %i seconds left. Good luck. \r" % (timer))
sys.stdout.flush()
cut_wire()
if timer == 0:
print("Boom!")
sys.exit()
and this is the cut_wire function:
def cut_wire():
wire_choice = raw_input("\n> ")
if wire_choice == "cut wire" or wire_choice == "Cut Wire":
stop_timer()
else:
print("Boom!")
sys.exit()
Of course it stops running when it plays the cut_wire function because "raw_input" command reads the text and wait for the user to put the text and press enter.
My suggestion is to check for they key press "Enter" and when then key was press, read the line. If the key wasn't press, just continue with your timer.
Regards.
Instead of using raw_input() use this function taken from here.
def readInput( caption, timeout = 1):
start_time = time.time()
sys.stdout.write('\n%s:'%(caption));
input = ''
while True:
if msvcrt.kbhit():
chr = msvcrt.getche()
if ord(chr) == 13: # enter_key
break
elif ord(chr) >= 32: #space_char
input += chr
if len(input) == 0 and (time.time() - start_time) > timeout:
break
print '' # needed to move to next line
if len(input) > 0:
return input
else:
return ""
Thearding option
To make sure that both functions run completely simultaneously you can use this example of threading event:
import threading
event = threading.Event()
th = theading.Thread(target=start_timer, args=(event, ))
th1 = theading.Thread(target=cut_wire, args=(event, ))
th.start()
th1.start()
th.join()
th1.join()
In your function you can set an event using event.set(), check it using event.is_set() and clear it using event.clear().
Only addressing your concerns, here is a quick fix using threading :
import time
import sys
import os
def start_timer():
global timer
timer = 10
while timer > 0:
time.sleep(1)
timer -= 1
sys.stdout.write ("There's only %i seconds left. Good luck. \r" % (timer))
sys.stdout.flush()
#cut_wire() ==> separate call is easier to handle
if timer == 0:
print("Boom!")
os._exit(0) #sys.exit() only exits thread
def cut_wire():
wire_choice = raw_input("\n> ")
if wire_choice == "cut wire" or wire_choice == "Cut Wire":
stop_timer()
else:
print("Boom!")
os._exit(0) #same reason
if __name__ == '__main__':
import threading
looper = threading.Thread(target=start_timer)
looper.start()
cut_wire()