Reputation: 1464
Why after I terminate a python script with ctrl+c
while the command subprocess.run('knife ec2 server create...', shell=True, check=True)
is running from this script, the control returns to the terminal session but after a few min/sec the shell command reappears in the terminal session and the shell command from subprocess.run
still running?
I think I saw the same issue with os.system
, for example os.system('ping 8.8.8.8')
.
^C
Waiting for EC2 to create the instance.....^CTraceback (most recent call last):
File "t.py", line 177, in <module>
subprocess.run(command, shell=True, check=True)
File "/usr/lib/python3.5/subprocess.py", line 695, in run
stdout, stderr = process.communicate(input, timeout=timeout)
File "/usr/lib/python3.5/subprocess.py", line 1064, in communicate
self.wait()
File "/usr/lib/python3.5/subprocess.py", line 1658, in wait
(pid, sts) = self._try_wait(0)
File "/usr/lib/python3.5/subprocess.py", line 1608, in _try_wait
(pid, sts) = os.waitpid(self.pid, wait_flags)
KeyboardInterrupt
$ ..............................................................................done
SSH Target Address: ec2()
Doing old-style registration with the validation key at /etc/chef/validation.pem...
Delete your validation key in order to use your user credentials instead
I tried also the below code but I got an error:
command = ('knife ec2 server create -N ' + fullname + ' -f ' + instance_type + ' -i ' + pem_file)...
p = subprocess.Popen(command, shell=True, stderr=subprocess.PIPE)
while True:
out = p.stderr.read(1)
if out == '' and p.poll() != None:
break
if out != '':
sys.stdout.write(out)
sys.stdout.flush()
error:
`sys.stdout.write(out) TypeError: write() argument must be str, not bytes'
Is there a simple way to run a shell command with python
like Ruby
with system()
?
Thanks
Upvotes: 1
Views: 3682
Reputation: 2325
the subprocess module spawns a new process. when you send the CTRL+C signal to your python code, you are existing your python application but the subprocess is still running and your code decides not to wait for the process to finish.
Try catching the Ctrl+C signal in your code, and then use Popen terminate call to end the subprocess before existing your application.
import shlex, subprocess
command_line = input()
args = shlex.split(command_line)
print(args)
p = subprocess.Popen(args) # Success!
Here is the API doc for the terminate call:
EDIT Here is sample demo code for python 2.7, the section of the code that prints strout doesn't apply for ping, because it will still output the ping result to the terminal, but I placed it there for reference.
import subprocess
import signal
import sys
command = 'ping {0}'.format('8.8.8.8')
p = subprocess.Popen(command, shell=True, stderr=subprocess.PIPE)
# callback for the Ctrl+C signal
def signal_handler(signal, frame):
print("CTRL+C received")
p.kill() # or terminate
p.wait()
sys.exit(0)
# register signal with the callback
signal.signal(signal.SIGINT, signal_handler)
# white subprocess hasn't finished
while p.poll() is None:
out = p.communicate()
print(out.stdoutdata)
Upvotes: 2