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))