19

I have some GPU test software i'm trying to automate using python3, The test would normally be run for 3 minutes then cancelled by a user using ctrl+c generating the following output

GPU test output

After exiting with ctrl+c the test can then be run again with no issue

When trying to automate this with subprocess popen and sending SIGINT or SIGTERM i'm not getting the same as if keyboard entry was used. The script exits abruptly and on subsequent runs cant find the gpus (assume its not unloading the driver properly)

from subprocess import Popen, PIPE
from signal import SIGINT
from time import time


def check_subproc_alive(subproc):
    return subproc.poll() is None

def print_subproc(subproc, timer=True):
    start_time = time()
    while check_subproc_alive(subproc):
        line = subproc.stdout.readline().decode('utf-8')
        print(line, end="")
        if timer and (time() - start_time) > 10:
            break


subproc = Popen(['./gpu_test.sh', '-t', '1'], stdin=PIPE, stdout=PIPE, stderr=PIPE, shell=False)

print_subproc(subproc)

subproc.send_signal(SIGINT)

print_subproc(subproc, False)

How can I send ctrl+c to a subprocess as if a user typed it?

**UPDATE

import subprocess


def start(executable_file):
    return subprocess.Popen(
        executable_file,
        stdin=subprocess.PIPE,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE
    )


def read(process):
    return process.stdout.readline().decode("utf-8").strip()


def write(process):
    process.stdin.write('\x03'.encode())
    process.stdin.flush()

def terminate(process):
    process.stdin.close()
    process.terminate()
    process.wait(timeout=0.2)


process = start("./test.sh")
write(process)
for x in range(100):
    print(read(process))
terminate(process)

Tried the above code and can get characters to register with dummy sh script however sending the \x03 command just sends an empty char and doesn't end script

3
  • 2
    Please post your code. Commented Aug 22, 2019 at 11:12
  • not really a duplicate, thats using pyserial not subprocess module Commented Aug 22, 2019 at 11:37
  • I spent a lot of hours on this, but find simpler solution from this post (new method) stackoverflow.com/a/60795888/3673470 So I'm starting process like that (all imports from subprocess): process = Popen(cmd, stdin=PIPE, creationflags=CREATE_NEW_PROCESS_GROUP) and when I'm closing it with that signal gracefully: process.send_signal(signal.CTRL_BREAK_EVENT) This is literally 2 lines, while other methods require external files / executables / etc. Commented Apr 12, 2024 at 22:02

2 Answers 2

14

I think you can probably use something like this:

import signal
try:
    p=subprocess...
except KeyboardInterrupt:
    p.send_signal(signal.SIGINT)
Sign up to request clarification or add additional context in comments.

7 Comments

Wouldnt this send SIGINT if a keyboard interrupt occured during the subprocess execution? im trying to automate that keyboard interrupt happening in the first place
if you want to send sigint without pressing ctrl+c, you can just use p.send_signal(signal.SIGINT) directly without the try, except block
That is what I want to do but sending SIGINT is not the same as when I run the gpu test script and manually press ctrl+c. Manually pressing ctrl+c causes the script to report error manual user intervention and it stops gracefully. Sending SIGINT stops the script dead with no teardown
I think it's because you have shell=False, can you try without that?
If i set shell as true the gpu test would have to complete before the next lines of code are executed
|
7

The following solution is the only one I could find that works for windows and is the closest resemblance to sending a Ctrl+C event.

import signal
os.kill(self.p.pid, signal.CTRL_C_EVENT)

4 Comments

This is nearly identical to self.p.send_signal(signal.CTRL_C_EVENT). In this case, it is checked if the process 'has already died'.
Could you elaborate on what self is in this context?
@Leonid self.p where p is the subprocess
I guess this doesn't work on Linux; AttributeError: module 'signal' has no attribute 'CTRL_C_EVENT'

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.