Parsing the lsblk output
lsblk

The -s option to lsblk was introduced to util-linux rather recently, in release 2.22.  You may experience compatibility issues on slightly older GNU/Linux installations.

But I don't see why you would want the -s option at all — it just gives you an inverted device tree.  For example, on my machine:


$ lsblk -o name -n -s -l
sda1
sda
sda2
sda
sr0
vg-root
sda3
sda
vg-var
sda3
sda
vg-data
sda3
sda



In the output, sda appears multiple times.  To understand the output, you need to drop the -l flag so that the list appears in tree form:


$ lsblk -o name -n -s
sda1
└─sda
sda2
└─sda
sr0
vg-root
└─sda3
  └─sda
vg-var
└─sda3
  └─sda
vg-data
└─sda3
  └─sda



Now, it's more apparent that the -s option isn't helpful.  If you drop it, then the output makes more sense:


$ lsblk -o name -n
sda
├─sda1
├─sda2
└─sda3
  ├─vg-root
  ├─vg-var
  └─vg-data
sr0
$ lsblk -o name -n -l
sda
sda1
sda2
sda3
vg-root
vg-var
vg-data
sr0



To list the devices on sda, it would be better to run lsblk -o name -n -l /dev/sda — that would immediately drop sr0 from consideration, for example.  Note that LVM volumes (such as vg-root above) would still appear in the output.  I don't think that doing a substring search (if x != disk and disk in x in your code) is a reliable filter.  It could be fooled if there are more than 26 physical disks: the 27th disk would be named sdaa.  It might also be fooled by exceptionally tricky naming of LVM volumes.

Subprocess execution

Whenever practical, I recommend avoiding the shell when executing subprocesses.  The shell introduces a set of potential security vulnerabilities — for example, shenanigans with the PATH environment variable.  Best practice would be to run the command with a specific executable and pre-parsed command-line options:

run('/bin/lsblk -o name -n -s -l'.split(), stdout=PIPE)


Alternative solution

I actually wouldn't bother with parsing the output of lsblk at all.  After all, lsblk is just a way to report the contents of the sysfs filesystem.  You would be better off inspecting /sys directly.

from glob import glob
from os.path import basename, dirname

def physical_drives():
    drive_glob = '/sys/block/*/device'
    return [basename(dirname(d)) for d in glob(drive_glob)]

def partitions(disk):
    if disk.startswith('.') or '/' in disk:
        raise ValueError('Invalid disk name {0}'.format(disk))
    partition_glob = '/sys/block/{0}/*/start'.format(disk)
    return [basename(dirname(p)) for p in glob(partition_glob)]