I have 2 scripts - one is running and when I press a button, a second script is launched.
That is working; but I would like to kill that second script when I release the button again.
The killing of the second script seems not to be working
below code of script 1
import RPi.GPIO as GPIO
import time
from time import sleep
import subprocess, os
from subprocess import check_call
buttonPin = 5
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False) #Display no error messages
GPIO.setup(buttonPin, GPIO.IN) # initialize button pin We have a physical 10k Resistor so no pull-up is required
try:
run = 0
while True:
if GPIO.input(buttonPin)==0 and run == 0:
print("Button pressed start second script")
subprocess.call(['python3', "2ndPython.py"])
run=1
while GPIO.input(buttonPin)==0:
time.sleep(0.01)
if GPIO.input(buttonPin)==1 and run == 1:
run = 0
print("Button NOT pressed - kill second script")
check_call(["pkill", "-9", "-f", "python3", "2ndPython.py"]) # Stop script
while GPIO.input(buttonPin)==1:
time.sleep(0.01)
except KeyboardInterrupt:
GPIO.cleanup()
code of my second script that I would like to kill when I release the button.
import time
from time import sleep
def main():
count = 0
while True:
count = count +1
# do whatever the script does
print("You have started this program X " + str(count) + " times now")
time.sleep(2)
if __name__ == "__main__":
main()
Can't seem to find why the second script is not killed.
Related
I wrote a Python3 script (shown below, repo here https://gitlab.com/papiris/gcode-motor-stutter-generator)
After I execute it on Linux (Raspberry Pi OS bullseye 32-bit) and either exit by ctrl+c or let it finish; I can't see what I write in that respective terminal tab anymore. The terminal (kde konsole) responds to commands, the text just isn't visible. I can open a new terminal tab and keep working, but the terminal tabs I run this script in never show the text I input again.
Why is this, and how can I fix it?
I tried searching for this topic, but couldn't find anything similar.
#!/usr/bin/env python3
from sys import stdout, stdin
from curtsies import Input
from threading import Thread
from queue import Queue, Empty
### non-blocking read of stdin
def enqueue_input(stdin, queue):
try:
with Input(keynames='curses') as input_generator:
for _input in iter(input_generator):
queue.put(_input)
except keyboardInterrupt:
sys.exit(1)
q=Queue()
t = Thread(target=enqueue_input, args=(stdin, q))
t.daemon = True # thread dies with the program
t.start()
def main():
while True:
try:
input_key = q.get(timeout=2)
except Empty:
print(f'printing continuously')
pass
else:
if input_key == 'n':
print('extrusion loop stopped, moving on')
break
if __name__ == "__main__":
main()
I have created an application using Tkinter , it will connect to SSH and run few commands. This process is running in a loop using scheduler.
After 1st iteration , command prompt gets stuck and wont resume its display till I press enter. It just wont display output on command prompt. I am writing that output into a file. even file is not getting updated till I press any key at command prompt. Looks like it waits for some input/key stroke to start next iteration.
After pressing enter I can see that it was already running at background as suddenly it displays lots of output on the screen.
How to run/display/focus it continuously ? I am using a scheduler so that my job will keep on running for few hours. But due to command prompt stuck issue I can not see whether my program is running or not using command prompt.
If I keep open my command prompt window , everything works smoothly, output window appears and output gets written into the file, if the window is minimized , output window does not show up and file is not getting updated.
Looks like it only works when it is in focus ( command prompt is not minimized)
Please help.
code is here:
import tkinter.messagebox
import paramiko
import time
from datetime import datetime, timedelta
import tkinter.messagebox
import tkinter
import sys
import apscheduler
from apscheduler.schedulers.blocking import BlockingScheduler
import babel.numbers # for exe
def display_output(targetopname):
hostname_ip = "192.168.1.101"
username = "admin"
password = "admin"
# create /append output file
output_file = open(targetopname, "a+")
port = 22
i = 0
while True:
try:
ssh = paramiko.SSHClient()
#ssh.load_system_host_keys()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname_ip, 22, username, password)
break
except paramiko.AuthenticationException:
print("Authentication failed when connecting to %s" % hostname_ip)
sys.exit(1)
except:
print("Could not SSH to %s, waiting for it to start" % hostname_ip)
i += 1
time.sleep(2)
if i == 3:
print("Could not connect to %s. Giving up" % hostname_ip)
sys.exit(1)
cmd_list = list()
c1 = "config global"
c2 = "get sys status"
c3 = "end"
cmd_list.append(c1)
cmd_list.append(c2)
cmd_list.append(c3)
op_tk = tkinter.Tk()
op_tk.wm_title("p2trial")
op_tk.geometry("600x400")
op_text_window = tkinter.Text(op_tk, height=600, width=400)
op_scrollbar = tkinter.Scrollbar(op_tk)
op_scrollbar.pack(side=tkinter.RIGHT, fill=tkinter.Y)
op_scrollbar.config(command=op_text_window.yview)
op_text_window.pack(side=tkinter.LEFT, fill=tkinter.Y)
channel = ssh.invoke_shell()
for command in cmd_list:
time.sleep(1)
channel.send(command + '\n')
time.sleep(0.30)
if channel.recv_ready():
time.sleep(0.30)
outlines = channel.recv(10240).decode("ascii")
op_text_window.insert(tkinter.END, outlines)
op_text_window.pack(side=tkinter.LEFT, fill=tkinter.Y)
op_tk.update()
output_file.write(outlines)
else:
print("\nNo data for command ", command)
time.sleep(2)
channel.close()
ssh.close()
output_file.close()
op_tk.destroy()
dtnow = datetime.now()
print("\n*** End of the function ", dtnow)
if __name__ == '__main__':
scheduler = BlockingScheduler()
x = datetime.now() + timedelta(seconds=1)
x += timedelta(seconds=1)
targetfilename = "output.txt"
scheduler.add_job(display_output, 'interval', minutes=3,
max_instances=5, start_date=x,
end_date='2021-10-12 11:00:00.000000',args=[targetfilename])
scheduler.start()
Looks like it is related to command prompt and not tkinter.
I have referred the solution :
Command prompt gets stuck and continues on enter key press
It is solving my problem.
Thank you everyone.
I want to know how to stop a running function outside of it. Here is how it should be:
def smth():
time.sleep(5) # Just an example
smth.stop()
Thanks for your help
Here's an example using the multiprocessing library:
from multiprocessing import Process
import time
def foo():
print('Starting...')
time.sleep(5)
print('Done')
p = Process(target=foo) #make process
p.start() #start function
time.sleep(2) #wait 2 secs
p.terminate() #kill it
print('Killed')
Output:
Starting...
Killed
Basically, what this code does is:
Create a process p which runs the function foo when started
Wait 2 seconds to simulate doing other stuff
End the process p with p.terminate()
Since p never passes time.sleep(5) in foo, it doesn't print 'Done'
Run this code online
I've read many of the questions here on SO, but none of the solutions seem to solve my problem. I have a file called "light_led.py" which looks like this
import RPi.GPIO as gpio
import time
# Set the mode for the GPIO numbering
gpio.setmode(gpio.BCM)
pin = 23
# Set the GPIO as output
gpio.setup(pin, gpio.OUT, initial=gpio.LOW)
try:
while True: # Run forever
gpio.output(pin, gpio.HIGH) # Turn on
time.sleep(1) # Sleep for 1 second
gpio.output(pin, gpio.LOW) # Turn off
time.sleep(1) # Sleep for 1 second
except KeyboardInterrupt:
# cleanup all GPIO
gpio.cleanup()
print('Cleaned up')
It simply toggles an LED on and off. This file is called in the following script
import RPi.GPIO as gpio
import time
import subprocess
import signal
# Set the mode for the GPIO numbering
gpio.setmode(gpio.BCM)
pin = 24
# Set the GPIO as input w/ pull up
gpio.setup(pin, gpio.IN, pull_up_down = gpio.PUD_UP)
# Initialize
pin_prev = gpio.input(pin)
while True:
pin = gpio.input(pin)
if (pin == 0) and (pin_prev == 1):
process = subprocess.Popen('python <PATH-TO-FILE>/light_led.py', shell=True)
print('Should be blinking')
if (pin == 1) and (pin_prev == 0):
process.send_signal(signal.SIGINT)
print('Should be off')
# Update previous state
pin_prev = pin
# Slight pause to debounce
time.sleep(0.05)
The files run fine and do what they're suppose to. The only problem I'm having is that I can't stop the blinking light by "flipping the switch". In other words, I'm having trouble with this process.send_signal(signal.SIGINT). There are not errors, so I don't have much to report.
I've tried process.terminate() and os.kill(process.pid, signal.SIGINT), both with no luck. I just want to stop the subprocess from running and continue with the main toggle script. From what I read, "signal.SIGINT" should invoke the "KeyboardInterrupt" in the subprocess...but maybe not?
I am trying to write function using Python multiprocessing that i can control it and pass "command" to cleanly terminate the process.
I looked for few examples and tried it out ,but didn't seems to work fro me
So basically i need to to run separate process function code that doing some while loop action
and when needed stop it by passing somehow command and exit
Please advice
Thanks
example 1
from multiprocessing import Process, Queue
def start_process(queue):
while True:
try:
m = queue.get()
if m == 'exit':
print ('cleaning up worker...')
# add here your cleaning up code
break
else:
print (m)
except KeyboardInterrupt:
print ('ignore CTRL-C from worker')
if __name__ == '__main__':
queue = Queue()
process = Process(target=start_process, args=(queue,))
process.start()
queue.put(12)
try:
process.join()
except KeyboardInterrupt:
print ('wait for worker to cleanup...')
queue.put('exit')
process.join()
example 2
import multiprocessing
import time
class MyProcess(multiprocessing.Process):
def __init__(self, ):
multiprocessing.Process.__init__(self)
self.exit = multiprocessing.Event()
def run(self):
while not self.exit.is_set():
pass
print ("You exited!")
def shutdown(self):
print ("Shutdown initiated")
self.exit.set()
if __name__ == "__main__":
process = MyProcess()
process.start()
print ("Waiting for a while")
time.sleep(3)
process.shutdown()
time.sleep(3)
print ("Child process state: %d" % process.is_alive())
both examples works fine for me - perhaps you're misunderstanding how they should work?
in the first example, when the main thread runs, it starts the child and sends 12. then it waits to join the child. at that point everything is stalled because the child is waiting for 'exit'. but if you then hit ctrl-C the 'exit' is sent, the child exits, and the second join is successful:
> python3.3 example1.py
12
^Cignore CTRL-C from worker
wait for worker to cleanup...
cleaning up worker...
>
if you just want the parent to send 'exit' and then for everything to end, use:
def start_process(queue):
while True:
try:
m = queue.get()
if m == 'exit':
print ('cleaning up worker...')
# add here your cleaning up code
break
else:
print (m)
except KeyboardInterrupt:
print ('ignore CTRL-C from worker')
print('goodbye cruel world')
if __name__ == '__main__':
queue = Queue()
process = Process(target=start_process, args=(queue,))
process.start()
queue.put(12)
print ('sending exit')
queue.put('exit')
process.join()
which gives:
> python3.3 my-example.py
sending exit
12
cleaning up worker...
goodbye cruel world
>
your second example also works (with the indentation fixed):
> python3.3 example2.py
Waiting for a while
Shutdown initiated
You exited!
Child process state: 0
>
(just wait a little). not sure what else you could have expected here.