How to call a system command with the specified time in Python?

I am creating a Python application that calls several system commands. However, I want him to complete these commands if they take too much time (e.g. 10 seconds). I tried to do it myself using some subprocesses - without much success. After searching stackoverflow, I found the following question: Using a module subprocess with a timeout

This one has an answer that almost works for me - the problem is that when the process is “completed”, it’s actually not - in fact the process remains in the background even after my script ends, Of course, it doesn’t is a desired effect, but I cannot find a workaround. Is there a solution to this problem?

Code from the specified answer (bad) for reference:

import subprocess, threading

class Command(object):
    def __init__(self, cmd):
        self.cmd = cmd
        self.process = None

    def run(self, timeout):
        def target():
            print 'Thread started'
            self.process = subprocess.Popen(self.cmd, shell=True)
            self.process.communicate()
            print 'Thread finished'

        thread = threading.Thread(target=target)
        thread.start()

        thread.join(timeout)
        if thread.is_alive():
            print 'Terminating process'
            self.process.terminate()
            thread.join()
        print self.process.returncode

command = Command("echo 'Process started'; sleep 2; echo 'Process finished'")
command.run(timeout=3)
command.run(timeout=1)
+4
source share
1 answer

Here you can find your answer:

How to end a python subprocess launched using shell = True

just add preexec_fn=os.setsidto the commandPopen

End use:

os.killpg(self.process.pid, signal.SIGTERM)

Instead:

self.process.terminate()

Do not forget import os,signal

so you get:

import subprocess, threading
import os,signal
class Command(object):
    def __init__(self, cmd):
        self.cmd = cmd
        self.process = None

    def run(self, timeout):
        def target():
            print 'Thread started'
            self.process = subprocess.Popen(self.cmd, shell=True, preexec_fn=os.setsid)
            self.process.communicate()
            print 'Thread finished'

        thread = threading.Thread(target=target)
        thread.start()

        thread.join(timeout)
        if thread.is_alive():
            print 'Terminating process'
            os.killpg(self.process.pid, signal.SIGTERM)
            thread.join()
        print self.process.returncode

command = Command("echo 'Process started'; sleep 2; echo 'Process finished'")
command.run(timeout=3)
command.run(timeout=1)
+1
source

Source: https://habr.com/ru/post/1568515/


All Articles