I'm trying to create application which needs to get user input data while it prints things in a console at the same time.
import threading
import time
def F1():
for i in range (100):
print (i)
time.sleep(1)
def input_data():
txt = input('>')
print(txt)
w1 = threading.Thread(target=F1)
w2 = threading.Thread(target=input_data)
w1.start()
w2.start()
But this way function input() stops all threads.
Is it possible to do it asynchronously in a python interpreter?
(I know that i could do it in tkinter easily.)
Related
I want to monitor the stdout of a program and whenever it prints something into stdout, I want to get a callback in python to process the gathered data.
The program I want to monitor is not written in python, but behaves similar to this dummy_script.py:
import datetime
import random
import time
i = 0
while True:
line = f"{datetime.datetime.now()} {i}"
print(line)
i += 1
time.sleep(random.uniform(0, 1))
For the main python script I tried something like this:
from threading import Thread
import os
def do_stuff():
command = f"python3 dummy_script.py"
os.system(command)
thread = Thread(target=do_stuff)
thread.daemon = True
thread.start()
So is there a way to create a callback when a new line is printed to stdout?
first of all, im a beginner.
Want i want to accomplish is that music plays while the script is executing.
What it does right now it plays the music, waits until the music is over and then executes the rest of the code. That is not what i want. Here my Code:
import os
import subprocess
import multiprocessing
import threading
from playsound import playsound
CurrentPath = os.path.dirname(os.path.normpath(__file__))
os.chdir(CurrentPath)
def music():
Music = "Music.mp4"
#subprocess.run(["ffplay", "-nodisp", "-autoexit", "-hide_banner", Music])
playsound("Music.mp4")
def other_things():
print("Hello World")
#musicp = multiprocessing.Process(target=music())
#restp = multiprocessing.Process(target=other_things())
musicp = threading.Thread(target=music())
restp = threading.Thread(target=other_things())
restp.start()
musicp.start()
LIke you can see i even tried multithreading but it still waits until the music is over before it goes to the rest of the code.
Don't call the functions in the target parameter of the Thread function - delete the brackets to reference the function, not its return value
musicp = threading.Thread(target=music) # instead of music()
restp = threading.Thread(target=other_things) # instead of other_things()
I am making a game/quiz in Python, but ran into a small issue. I made a function to print one letter at a time, but when I use that function for an input, it does not work and prints all at once. I've tried making a string for the input and multiple other things. To fix this temporarily, I have just been printing my question, and then using an input function to make an input, but I'm wondering if there is a better way. Here is my code:
import time
import sys
def input1():
input("")
def oneprint(s):
for c in s:
sys.stdout.write(c)
sys.stdout.flush()
time.sleep(0.05)
oneprint("Welcome. This is a very easy test. Do as you are told.")
time.sleep(3)
q1 = "\nLet's get started. What is my favorite color?"
oneprint(q1)
input1()
I think you may want to add the same for loop that requires c inside of your script in your input1 function, here is an example of how you could do such a thing:
import time
import sys
def oneprint(s):
for c in s:
sys.stdout.write(c)
sys.stdout.flush()
time.sleep(0.05)
def input1():
inp = input("")
oneprint(inp)
oneprint("Welcome. This is a very easy test. Do as you are told.")
time.sleep(3)
q1 = "\nLet's get started. What is my favorite color?"
oneprint(q1)
input1()
if you try this it will print the desired color that was answered by the player by getting the input and getting each letter and writing it and flushing it through the oneprint function.
This will display the input and oneprint it:
import time
import sys
def oneprint(s):
for c in s:
sys.stdout.write(c)
sys.stdout.flush()
time.sleep(0.05)
oneprint("Welcome. This is a very easy test. Do as you are told.")
time.sleep(3)
oneprint("\nLet's get started. What is my favorite color?")
oneprint(input("\n"))
This will hide the input, and oneprint it:
import time
import sys
from getpass import getpass
def oneprint(s):
for c in s:
sys.stdout.write(c)
sys.stdout.flush()
time.sleep(0.05)
oneprint("Welcome. This is a very easy test. Do as you are told.")
time.sleep(3)
oneprint("\nLet's get started. What is my favorite color?")
oneprint(getpass("\n>"))
Where getpass is a password formatted input
I figured out the answer. If anyone else is having this issue you should just do:
input(oneprint(Blah Blah Blah Your Question Here))
How can I print directly after my input without waiting until the user answered the input statement?
def InputSaveName():
try:
import os, sys, time, pickle, colorama
except Exception as e:
print("Some modules are mssing! Install them and try again! {}".format(e))
colorama.init()
print("+----------------------+")
print("What is your name adventurer?")
name = input("> ")
print("+----------------------+")
I want the bottom line to print without waiting for the user to put something in the input statement. In short: I want the code to run simultaneously.
This seems to be an XY problem. You do not really want to use threading to run multiple lines of code at once. To build a complex full-screen terminal application, you should have a look at curses:
import curses
def getname(stdscr):
stdscr.clear()
stdscr.addstr(0, 0, "+---------------------------+")
stdscr.addstr(1, 0, "What is your name adventurer?")
stdscr.addstr(2, 0, "> ")
stdscr.addstr(3, 0, "+---------------------------+")
curses.echo()
return stdscr.getstr(2, 3, 20)
s = curses.wrapper(getname)
print("Name is", s)
This only asks for the name and then returns, but you can also add lines, or replace existing lines on the existing screen and refresh the screen.
Without being 100% sure if it works in the specific examples you have typed in your question because of access to the standard output.
If you want to run things in parallel you can read about threads / subprocess https://docs.python.org/3/library/subprocess.html
or fork / multiprocessing
https://docs.python.org/3/library/multiprocessing.html
EDIT after op's EDIT ;-)
What you want to do seems very similar to what's described in this question Python nonblocking console input
This might be what you are looking for.
There is a "background process" running while waiting for your input using two separate threads.
import time
import threading
def myInput():
print("Type your name when ready!")
name = input()
print("Your name is: ", name)
def backgroundProcess():
while (True):
print("Some code is running...")
time.sleep(1)
inputThread = threading.Thread(target=myInput)
processThread = threading.Thread(target=backgroundProcess)
inputThread.start()
processThread.start()
You can use threading or multiprocessing modules:
import threading
def makeAsomethingOne():
print('I am One!')
def makeAsomethingTwo(printedData=None):
print('I am Two!',printedData)
name = input("> ")
firstThread = threading.Thread(target=makeAsomethingOne)
twiceThread = threading.Thread(target=makeAsomethingTwo,args=[name])
firstThread.start()
twiceThread.start()
This code runs almost simultaneously.
I'm struggling with a issue for some time now.
I'm building a little script which uses a main loop. This is a process that needs some attention from the users. The user responds on the steps and than some magic happens with use of some functions
Beside this I want to spawn another process which monitors the computer system for some specific events like pressing specif keys. If these events occur then it will launch the same functions as when the user gives in the right values.
So I need to make two processes:
-The main loop (which allows user interaction)
-The background "event scanner", which searches for specific events and then reacts on it.
I try this by launching a main loop and a daemon multiprocessing process. The problem is that when I launch the background process it starts, but after that I does not launch the main loop.
I simplified everything a little to make it more clear:
import multiprocessing, sys, time
def main_loop():
while 1:
input = input('What kind of food do you like?')
print(input)
def test():
while 1:
time.sleep(1)
print('this should run in the background')
if __name__ == '__main__':
try:
print('hello!')
mProcess = multiprocessing.Process(target=test())
mProcess.daemon = True
mProcess.start()
#after starting main loop does not start while it prints out the test loop fine.
main_loop()
except:
sys.exit(0)
You should do
mProcess = multiprocessing.Process(target=test)
instead of
mProcess = multiprocessing.Process(target=test())
Your code actually calls test in the parent process, and that call never returns.
You can use the locking synchronization to have a better control over your program's flow. Curiously, the input function raise an EOF error, but I'm sure you can find a workaround.
import multiprocessing, sys, time
def main_loop(l):
time.sleep(4)
l.acquire()
# raise an EOFError, I don't know why .
#_input = input('What kind of food do you like?')
print(" raw input at 4 sec ")
l.release()
return
def test(l):
i=0
while i<8:
time.sleep(1)
l.acquire()
print('this should run in the background : ', i+1, 'sec')
l.release()
i+=1
return
if __name__ == '__main__':
lock = multiprocessing.Lock()
#try:
print('hello!')
mProcess = multiprocessing.Process(target=test, args = (lock, ) ).start()
inputProcess = multiprocessing.Process(target=main_loop, args = (lock,)).start()
#except:
#sys.exit(0)