Home > front end >  Subprocess does not store output in variable
Subprocess does not store output in variable

Time:09-17

I am trying to capture the output of this command:

ls -l /sys/class/net/e*/device/virtfn*

in my python script using the subprocess library.

The output of this command is:

lrwxrwxrwx. 1 root root 0 Sep  7 14:52 /sys/class/net/enp1s0f0/device/virtfn0 -> ../0000:01:10.0
lrwxrwxrwx. 1 root root 0 Sep  7 14:52 /sys/class/net/enp1s0f0/device/virtfn1 -> ../0000:01:10.2
lrwxrwxrwx. 1 root root 0 Sep  7 14:52 /sys/class/net/enp1s0f0/device/virtfn2 -> ../0000:01:10.4
lrwxrwxrwx. 1 root root 0 Sep  7 14:52 /sys/class/net/enp1s0f0/device/virtfn3 -> ../0000:01:10.6
lrwxrwxrwx. 1 root root 0 Sep  7 14:52 /sys/class/net/enp1s0f0/device/virtfn4 -> ../0000:01:11.0
lrwxrwxrwx. 1 root root 0 Sep  7 14:52 /sys/class/net/enp1s0f0/device/virtfn5 -> ../0000:01:11.2
lrwxrwxrwx. 1 root root 0 Sep  7 14:52 /sys/class/net/enp1s0f0/device/virtfn6 -> ../0000:01:11.4
lrwxrwxrwx. 1 root root 0 Sep  7 14:52 /sys/class/net/enp1s0f0/device/virtfn7 -> ../0000:01:11.6
lrwxrwxrwx. 1 root root 0 Sep  7 14:52 /sys/class/net/enp1s0f1/device/virtfn0 -> ../0000:01:10.1
lrwxrwxrwx. 1 root root 0 Sep  7 14:52 /sys/class/net/enp1s0f1/device/virtfn1 -> ../0000:01:10.3
lrwxrwxrwx. 1 root root 0 Sep  7 14:52 /sys/class/net/enp1s0f1/device/virtfn2 -> ../0000:01:10.5
lrwxrwxrwx. 1 root root 0 Sep  7 14:52 /sys/class/net/enp1s0f1/device/virtfn3 -> ../0000:01:10.7
lrwxrwxrwx. 1 root root 0 Sep  7 14:52 /sys/class/net/enp1s0f1/device/virtfn4 -> ../0000:01:11.1
lrwxrwxrwx. 1 root root 0 Sep  7 14:52 /sys/class/net/enp1s0f1/device/virtfn5 -> ../0000:01:11.3
lrwxrwxrwx. 1 root root 0 Sep  7 14:52 /sys/class/net/enp1s0f1/device/virtfn6 -> ../0000:01:11.5
lrwxrwxrwx. 1 root root 0 Sep  7 14:52 /sys/class/net/enp1s0f1/device/virtfn7 -> ../0000:01:11.7

The code in my script:

def getMacOfBusSlotFunction(self, slotbus, slotslot, slotfunction):
   myParentDevicesProcess = subprocess.Popen(['ls','-l','/sys/class/net/e*/device/virtfn*'])

    stdout , stderr = myParentDevicesProcess.communicate()
    print(stdout.decode("utf-8"))

I used Retrieving the output of subprocess.call() as a basis.

I added the .decode("utf-8") part as I thought maybe the output was being returned as bytes. Including it and excluding it still give the same result...

The actual output I get from running this is a blank line (\n).

I expect the output to be the actual output of the command.

CodePudding user response:

You forgot to tell Popen to capture the output/stderr; by default it just lets it go to the terminal. To fix, you just need to tell it to capture them via pipes to the parent process:

myParentDevicesProcess = subprocess.Popen(['ls','-l','/sys/class/net/e*/device/virtfn*'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)

Of course, that still won't work because glob expansion is a property of the shell, not the ls command, and you're not running your command through a shell (nor should you). You could have Python do the glob expansion for you to roughly match the shell with (putting import glob at the top of the file):

myParentDevicesProcess = subprocess.Popen(['ls','-l']   glob.glob('/sys/class/net/e*/device/virtfn*'), stdout=subprocess.PIPE, stderr=subprocess.PIPE)

CodePudding user response:

Popen (or any subprocess call), without shell=True, cannot use shell features like wildcard expansion. If you had examined standard error too, you would have discovered an error message that ls could not find a file named literally /sys/class/net/e*/device/virtfn.

The trivial fix is to use a shell (and probably switch back to avoid bare Popen).

listing = subprocess.check_output('ls -l /sys/class/net/e*/device/virtfn', shell=True)

In some ways, a better solution would be to use Python's native functions to extract the information you need, rather than attempt to parse ls output but since we don't know what information you want, that's a bit hard to pin down. If your ultimate goal is to resolve the symlinks, try

import glob
import os

for symlink in glob.glob('/sys/class/net/e*/device/virtfn'):
    print(os.readlink(symlink))
  • Related