1

I was trying to write an automated task with Python3 and using subprocess.call as I need to run some shell commands as part of the script, but found one of the outputs was not printing in the right order as I expected.

Portion of it:

On Python2:

[root@server101 ~]# cat check_kernel.py
#!/usr/bin/env python
import subprocess
print "Current running kernel version on the system is:\n", subprocess.call(["uname", "-r"])

Output:

[root@server101 ~]# ./check_kernel.py
Current running kernel version on the system is:
3.10.0-1160.45.1.el7.x86_64
0

On Python3:

[root@server101 ~]# cat check_kernel.py
#!/usr/bin/env python3
import subprocess
print ("Current running kernel version on the system is:\n", subprocess.call(["uname", "-r"]))

Output:

[root@server101 ~]# ./check_kernel.py
3.10.0-1160.45.1.el7.x86_64
Current running kernel version on the system is:
 0

So what is the real difference there happening with subprocess.call when working with Python3?.

Am I missing something or I shouldn't be using subprocess.call with Python3 and changing it to subprocess.run or subprocess.Popen is the only way to get subprocess worked with Python3 ?.

vjwilson
  • 754
  • 2
  • 14
  • 30
  • Does this answer your question? [Retrieving the output of subprocess.call()](https://stackoverflow.com/questions/1996518/retrieving-the-output-of-subprocess-call) – Adam.Er8 Jan 23 '22 at 13:19
  • What happens is that first the subprocess runs, and it itself prints the output, then it returns `0`, only then `print` can execute, and you get you own string + the `0` – Adam.Er8 Jan 23 '22 at 13:21
  • Adam, before saying it is a duplicate post, are you saying that subprocess.call behaviour is always like this on Python3? and if you check the same code with python2, it works fine. Just curious to know what is the difference. – vjwilson Jan 23 '22 at 13:24
  • Nope, same thing in Python 2. `call()` returns the exit code of the subprocess https://docs.python.org/2.7/library/subprocess.html#subprocess.call – Adam.Er8 Jan 23 '22 at 13:37
  • Can you run the same one with `#!/usr/bin/env python` ?, you can see it prints the desired output. – vjwilson Jan 23 '22 at 13:40
  • Well, not on my machine... And base on the very clear documentation, it shouldn't on any machine. – Adam.Er8 Jan 23 '22 at 14:00
  • @Adam.Er8 that is the part I am confused as well and the main reason I posted it here :) Please check the screenshot as I see the difference for the same code between Python 2 and Python3 on a Centos 7 machine. I get the difference on my local linux machine as well https://www.dropbox.com/s/jufg56c1i24wbn2/p2_vs_p3_subprocess_call.jpg?dl=0 – vjwilson Jan 23 '22 at 14:18

1 Answers1

1

Your subprocess prints the output by itself, and the function returns the return code. The print order could be influenced by Python's output buffering settings.

Just use subprocess.check_output to get the output that the command would print.

import subprocess, shutil
print ("Current running kernel version on the system is:\n", subprocess.check_output([shutil.which("uname"), "-a"]))

edit

As I imagined, the Python 2 version is

print "Current running kernel version on the system is:\n", subprocess.call(["uname", "-r"])

The Python 2 print statement evaluates and prints each expression in sequence.

The Python 3 print function is just a regular function, so arguments are evaluated first, and the function prints the evaluated values

Since the side effect of invoking uname is to print the uname, it gets printed first, followed by print doing its thing - printing the text and the return value of call, the zero return code.

AKX
  • 152,115
  • 15
  • 115
  • 172
  • Hi AKX, I appreciate your help, but that unfortunately does not help to clear my doubt. If you can re-check the whole post(I moderated it some minutes ago). The questions sticks to subprocess.call and the difference you see with it between python 2 and 3. – vjwilson Jan 23 '22 at 14:45
  • The point is you're using a call that has `uname` itself print output, but you're using it in a context where it's obvious you'd want to manage printing yourself. – AKX Jan 23 '22 at 14:47
  • Hmm ok, so that is what happening with Python3 when running that code? and Python2 does it quite normal? – vjwilson Jan 23 '22 at 14:51
  • Before we wonder further about this, please edit your Python 2 script into your original question and make sure that exact script indeed works as you expect. (Since the print statement became a function in Python 3, it's unlikely that the Python 2 and Python 3 versions are exactly the same.) – AKX Jan 23 '22 at 14:57
  • Sure, I edited the question and made it clear. Now you can see what I am trying to know :) Thanks again. – vjwilson Jan 23 '22 at 15:04
  • @JohnW Yep, so see my edit - it should make things clear. – AKX Jan 23 '22 at 15:07