Break Loop in python without pressing Ctr-C, "agnostic" to OS - python

An easy way to end an infinite for loop in python is by using Ctrl-C, e.g.:
try:
while True:
print '-',
except KeyboardInterrupt:
print 'done'
However, I want to use some other than Ctrl-C key because on other colleagues machines that might be interpreted by their gui environment (e.g. pycharm) as copy. Is there a way to do this? I need a solution that works both in windows and linux...

Ctrl+C on Linux sends a kill signal to the Python process. I don't think the Python script will be able to override the default behavior of the operating system.

Related

Python prevent subprocess from consuming keypress

I have a python script starting an .exe program in Windows. I want to be able to terminate this program by pressing "ESC". But I can't see the keypress in my Python program, it is read by the .exe program and consumed. How can I start the .exe program so that it does not read from stdin/keyboard. I do not need to send any keyboard commands to the .exe program.
This is the code I use:
pid = subprocess.Popen(functionCall)
while ((pid.poll()) or (pid.returncode == None)):
if msvcrt.kbhit() and msvcrt.getch()==chr(27):
print("ESC detected")
pid.kill()
pid.wait()
else:
print("Sleep")
time.sleep(1)
print("Exit while")
This is NOT possible.
The parent process (in this case Python) has no direct control (other than to send signals and read from stdout/stderr and send to stdin) over the subprocess.
You will need to handle this in the .EXE (Windows executable) itself; assuming you have the source code and can modify it.
Looks lite my problem wasn't the subprocess catching the keypress. But my handling of reading the keypress and analysing key value. Sorry for disturbing.
Solution to my problem:
msvcrt.getch().decode()==chr(27)
instead of:
msvcrt.getch()==chr(27)

Python: GUI for continuously running script

I am writing a script which will run continuously on a computer. As it has to run on a computer without python installation, I am planning to convert it to executable. I also want to have a GUI to start and stop this application but I don't want this GUI to be opened all the time. I mean if the GUI is closed, I don't want the executable to stop running. It should stop only if user presses stop button on GUI. This GUI is just a interface for users to start and stop the executable.
How can I achieve this behavior?
The obvious solution is to have two separate programs: a backgrounder/daemon/agent/service that just chugs along in the background detached from user input and output, and a GUI program to control it. A nice advantage of this design is that you can also have a command-line program to control it, if you ever want to ssh in remotely, or control it from a script.
The traditional Unix way of handling this is to use a daemon designed like a system service (even if it's run like a normal user): it writes its pid to a file when it starts up, and the control program reads that file and sends a signal to the pid that it finds to kill it.
So, the control program has functions something like this:
def is_running():
try:
with open(PID_PATH) as f:
pid = int(f.read())
os.kill(pid, 0)
except Exception:
return False
else:
return True
def stop():
with open(PID_PATH) as f:
pid = int(f.read())
os.kill(pid, signal.SIGUSR1)
def start():
subprocess.check_call(DAEMON_PATH)
Of course in real life, you'll want some better error handling. Also, which signal you use depends on whether you want the daemon to die hard and instantly, or to gracefully shut down. And so on.
An alternative is to have the background process listen on a socket—whether TCP with a known port, or a Unix socket with a known filename—and communicate with it that way. This allows you to do fancier things that just start and stop.
On Windows, the details aren't quite the same, but you can do something similar.
Finally, Windows, OS X, and various linux distros also all have platform-specific ways of wrapping this kind of thing up at a higher level, so you might want to build a Windows Service, LaunchAgent, etc.
Thanks #abarnert.I used your method and converted your code for windows. Please see below my solution which works. It's starting and stopping helloworld.exe. I have removed error handling to keep it simple.
import subprocess
import time
def startprocess():
#start helloworld.exe
process = subprocess.Popen(['helloworld.exe'])
#Write down the prog id into a file for later use
f = open('progid.txt','w')
f.writelines(str(int(process._handle)))
f.close()
def endprocess():
f = open('progid.txt','r')
progid = int(f.read())
f.close()
# Kill the process using pywin32
import win32api
win32api.TerminateProcess(progid, -1)
startprocess()
time.sleep(60) #wait for 60 second before kill
endprocess()

How to stop a multi-threaded Python script from outside

I have a Python program that uses multiple daemon threads. I want to stop the program from outside, preferably from another Python script.
I've tried with kill <pid> from shell, just for a test, but it doesn't work with multi-threaded scripts.
One way would be to make the program check some file every n-seconds as a flag for termination. I'm sure there's some better way I can do this.
Note that I'd like to stop the program cleanly, so some message from outside in a form of an exception would be ideal, I think.
EDIT:
Here's an example of how I did it at the moment:
try:
open('myprog.lck', 'w').close()
while True:
time.sleep(1)
try:
open('myprog.lck').close()
except IOError:
raise KeyboardInterrupt
except KeyboardInterrupt:
print 'MyProgram terminated.'
Deleting file myprog.lck will cause the script to stop. Is the example above bad way to do this?
Use the poison pill technique. Upon receipt of a pill (a special message) your program must handle it and die.. The way you're doing it its ok, but for something more elegant, you should implement a kind of communication between your "killing script" and your main program. For a start, have a look in the standard library for Interprocess Communication and Networking.
I would install a signal handler as described in http://www.doughellmann.com/PyMOTW/signal/index.html#signals-and-threads
You can enter kill -l in your shell to get a list of available signals.
You should be able to kill it from the shell with kill -9 <pid>.

Make running python script more responsive to ctrl c?

We are running a very large framework of python scripts for test automation and I do really miss the opportunity to kill a running python script with ctrl + c in some situations on Windows.
When the script might be doing some socket communications with long time-outs the only options sometimes is to kill the DOS window.. Is there any options I have missed?
Rather than using blocking calls with long timeouts, use event-driven networking. This will allow you never to have long periods of time doing uninterruptable operations.
Look for instances of:
try:
some code
except:
# catches all exceptions, including ^C
Change to:
try:
some code
except Exception:
# catches most exceptions, but not KeyboardInterrupt or SystemExit

Python: Can't continually catch keyboardinterrupt in Windows?

In Python, I wrote the following code to see if I could get my program to not terminate upon Control+C like all those fancy terminal apps such as Vim or Dwarf Fortress.
def getinput():
x = input('enter something: ')
while True:
try:
getinput()
except KeyboardInterrupt:
pass
Unfortunately, in the Windows console, this script terminates after a few seconds. If I run it in IDLE, it works as expected. Python version is 3.2.1, 3.2 acted the same. Am I doing something wrong?
EDIT: If I hold down, Control+C, that is.
In order to not terminate on Control-C you need to set a signal handler.
From the Python doc here
Python installs a small number of
signal handlers by default: SIGPIPE is
ignored (so write errors on pipes and
sockets can be reported as ordinary
Python exceptions) and SIGINT is
translated into a KeyboardInterrupt
exception. All of these can be
overridden.
So you would need to install a signal handler to catch the SIGINT signal and do what you want on that.
The behavior with IDLE is probably that they have a handler installed that blocks the application exit.

Categories

Resources