Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

sending keyboard interrupt programmatically

Tags:

python

windows

An application that asks for a keyboard interrupt. How can I send for a keyboard interrupt programmatically? I need it for automation. Like <C-c> or <C-x>

KeyboardInterrupt 
like image 867
user971797 Avatar asked Sep 29 '11 19:09

user971797


3 Answers

Code running in a separate thread can cause a KeyboardInterrupt to be generated in the main thread by calling thread.interrupt_main(). See https://docs.python.org/2/library/thread.html#thread.interrupt_main

like image 172
rakslice Avatar answered Sep 28 '22 13:09

rakslice


Since you mention automation I assume you want a SendKeys for Python. Try this: http://rutherfurd.net/python/sendkeys/

like image 22
David Heffernan Avatar answered Sep 28 '22 13:09

David Heffernan


My suggestion to solve this problem is to use the following code pattern. I used it to programmatically start a tensorboard server and shut it down by sending a CTRL-C when the object it belongs to is deleted. Generally speaking, this should work for any example that provokes a subprocess that is supposed to be send a KeyBoardInterrupt:

  1. Import signal and subprocess

    import signal
    import subprocess 
    
  2. Create the subprocess using subprocess.Popen. Important: set the creationflags parameter to subprocess.CREATE_NEW_PROCESS_GROUP. This is necessary to later be able to send the KeyboardInterrupt event.

    command= <enter your command that is supposed to be run in different process as a string> 
    process = subprocess.Popen(command.split(),stdout=subprocess.PIPE,stdin=subprocess.PIPE,creationflags=subprocess.CREATE_NEW_PROCESS_GROUP) 
    
  3. Wherever you want to send the keyboardInterrupt, do the following:

    process.send_signal(signal.CTRL_C_EVENT)
    

That is it! Please see the the official subprocess documentation for insights on why the creationflags parameter of popen has to be set that way.


This is how the code looks for my example in a less generic way:

import signal
import subprocess
import time

class ExperimentTracker():
   
     def __init__(self):
         self.tensorboard_process=None

     def __del__(self):
         #shutdown tensorboard server and terminate process
         self.tensorboard_process.send_signal(signal.CTRL_C_EVENT)
         time.sleep(0.2)
         self.tensorboard_process.kill()

     def launch_tensorboard(self):
         #launch tensorboard
         bashCommand= "tensorboard --logdir runs" 
         self.tensorboard_process = subprocess.Popen(bashCommand.split(),stdout=subprocess.PIPE,stdin=subprocess.PIPE,creationflags=subprocess.CREATE_NEW_PROCESS_GROUP) 
         time.sleep(2) #sleep for 2 seconds to give tensorboard time to be launched
         
like image 44
nick Avatar answered Sep 28 '22 13:09

nick