I was trying to understand why this is happening. I'm calling a command to restart networking on Ubuntu server 12.04.
Fast execution
When I call the command using one of following three ways it takes around 0.1 seconds to execute:
os.system
subprocess.call
terminal session:
root@ubuntu:~# time /etc/init.d/networking restart
* Running /etc/init.d/networking restart
* Reconfiguring network interfaces...
real 0m0.105s
root@ubuntu:~# time python -c "import os;
> os.system('/etc/init.d/networking restart')"
* Running /etc/init.d/networking restart
* Reconfiguring network interfaces...
real 0m0.111s
root@ubuntu:~# time python -c "import subprocess;
> subprocess.call(['/etc/init.d/networking', 'restart'])"
* Running /etc/init.d/networking restart
* Reconfiguring network interfaces...
real 0m0.111s
Slow execution
However if I use subprocess.check_output
or Popen and try and read the output it takes 23 seconds. Way slower. It seems this dramatic difference only happens when I try and use a function that will return the commands output. I would like to understand why this is happening and find a solution to execute this command and get it's output without it taking so long.
terminal session:
root@ubuntu:~# time python -c "import subprocess;
> print subprocess.check_output(['/etc/init.d/networking', 'restart'])"
* Running /etc/init.d/networking restart
* Reconfiguring network interfaces...
real 0m23.201s
root@ubuntu:~# time python -c "from subprocess import Popen, PIPE;
> print Popen(['/etc/init.d/networking', 'restart'], stdout=PIPE).stdout.read()"
* Running /etc/init.d/networking restart
* Reconfiguring network interfaces...
real 0m23.201s
Update
One of the comments suggested trying out the tee command. The results where very interesting. In the terminal without any involvement of python if tee is used it takes the same 23 seconds. I am still curious why but at least this might give more of a clue as to what's going on.
root@ubuntu:~# time /etc/init.d/networking restart | tee out.txt
* Running /etc/init.d/networking restart
* Reconfiguring network interfaces...
real 0m23.181s
The code below is based on the excellent comment J.F. Sebastian made. The code below runs in 0.1 seconds as expected and returns the output of the command to a string.
from subprocess import check_call, STDOUT
from tempfile import NamedTemporaryFile
with NamedTemporaryFile() as f:
check_call(['/etc/init.d/networking', 'restart'], stdout=f, stderr=STDOUT)
f.seek(0)
output = f.read()