0

I'm working on a raspberry pi and wanted to extract cpuinfo from /proc/cpuinfowith Python. This is the following command I want to execute:

cat /proc/cpuinfo  | grep 'model name\|Hardware\|Serial' | uniq

I get the following output when I run the command directly on the Raspberry pi terminal :

model name      : ARMv7 Processor rev 4 (v7l)
Hardware        : BCM2835
Serial          : 0000000083a747d7

which is what I expect as well. I want to get this into a Python list, so I used the subprocess.check_output() method and used a .split() and .splitlines() considering the way it is formatted. But invoking the same command by using subprocess.check_output() I do not get what I expect. Here's the code I ran in Python :

import subprocess
items = [s.split('\t: ') for s in subprocess.check_output(["cat /proc/cpuinfo  | grep 'model name\|Hardware\|Serial' | uniq "], shell=True).splitlines()]

The error I receive is as follows:

TypeError: a bytes-like object is required, not 'str'

Trying to debug issue: 1)On removing the .splitlines() at the end. ie:

items = [s.split('\t: ') for s in subprocess.check_output(["cat /proc/cpuinfo  | grep 'model name\|Hardware\|Serial' | uniq "], shell=True)

Now the Output error is:

AttributeError: 'int' object has no attribute 'split'

2)On removing .split:

items = [s for s in subprocess.check_output(["cat /proc/cpuinfo  | grep 'model name\|Hardware\|Serial' | uniq "], shell=True)

Output items now holds the following:

>>> items

[109, 111, 100, 101, 108, 32, 110, 97, 109, 101, 9, 58, 32, 65, 82, 77, 118, 55, 32, 80, 114, 111, 99, 101, 115, 115, 111, 114, 32, 114, 101, 118, 32, 52, 32, 40, 118, 55, 108, 41, 10, 72, 97, 114, 100, 119, 97, 114, 101, 9, 58, 32, 66, 67, 77, 50, 56, 51, 53, 10, 83, 101, 114, 105, 97, 108, 9, 9, 58, 32, 48, 48, 48, 48, 48, 48, 48, 48, 56, 51, 97, 55, 52, 55, 100, 55, 10]

Almost seems like grep is behaving differently than I expect it. but I'm not able to zero-in on what exactly is the problem. What are these numbers? Is it values that grep returns? Please help on how to resolve.

Thanks

  • just read the `/proc/cpuinfo` and parse it in python – Alex P. May 14 '18 at 16:45
  • @AlexP. You're right! Its a duplicate. I did a lot of searching but never came across that post. That answer works. Should I update the answer here ? – Samuel George May 14 '18 at 16:47
  • also the `cat | grep` is an anti-pattern on its own. `grep` takes the input file name as a parameter - there is no need to spawn multiple processes for that. still in this case the best way is to just use python built-in file IO instead of subprocess – Alex P. May 14 '18 at 17:12
  • @AlexP. You're right. I was just thinking on debugging this problem rather than on another approach. IO would definitely be easy! Thanks – Samuel George May 14 '18 at 17:23

2 Answers2

0

In Python3 the subprocess.check_output() returns bytes which need to be decoded to the string before string functions could be used. Another option is to use the legacy subprocess.getoutput() function.

The following code does the job for me:

items = [s.split('\t: ') for s in subprocess.getoutput(["cat /proc/cpuinfo  | grep 'model name\|Hardware\|Serial' | uniq "]).splitlines()]
Alex P.
  • 30,437
  • 17
  • 118
  • 169
0

Compare with:

items = dict(s.split('\t: ') for s in open('/proc/cpuinfo', 'r').read().splitlines() if s.startswith(('model name', 'Hardware', 'Serial')))
Alex P.
  • 30,437
  • 17
  • 118
  • 169