user2695452
user2695452

Reputation: 1

Execute bash commands from python - OSError: [Errno 2]

I am pretty new to Python. When i execute the following command to get the total CPU core count on my x86 server using the following python code i get an error as below;

########################Code#######################
#!/usr/bin/python
import os
import re
import subprocess
os.system('clear')

#CPU core count check
flag=0
p = subprocess.Popen(['cat /proc/cpuinfo | grep -i processor | wc -l'], stdout=subprocess.PIPE)
print p.communicate(1)

##############################Output####################

Traceback (most recent call last):
  File "./chk_config.py", line 9, in <module>
    p = subprocess.Popen(['cat /proc/cpuinfo | grep -i processor | wc -l'], stdout=subprocess.PIPE)
  File "/usr/lib64/python2.7/subprocess.py", line 711, in __init__
    errread, errwrite)
  File "/usr/lib64/python2.7/subprocess.py", line 1327, in _execute_child
    raise child_exception
OSError: [Errno 2] No such file or directory

os.popen works, but I don't want to use os.popen since it prints None at the end of the total core count which i want to omit/

Upvotes: 0

Views: 581

Answers (1)

Note: use the following, because Python already knows how many CPUs you have, and this is guaranteed to be far more portable than any bash command that you can come up with:

>>> import multiprocessing
>>> multiprocessing.cpu_count()
4

Regarding your command:

First of all, subprocess will not understand | within the command, or generally run the command in shell, unless shell=True is provided. Instead your program will try to find a command /usr/bin/cat\ /proc/cpuinfo\ \|\ grep\ -i\ processor\ \|\ wc\ -l, which of course fails.

The solution is to add shell=True to execute the command in shell:

p = subprocess.Popen('grep -i processor /proc/cpuinfo | wc -l',
                     stdout=subprocess.PIPE, shell=True)

However, it is also possible to construct the pipeline in Python:

grep = subprocess.Popen('grep -i processor /proc/cpuinfo'.split(), stdout=subprocess.PIPE)
wc = subprocess.Popen('wc -l'.split(), stdin=grep.stdout, stdout=subprocess.PIPE)
output = wc.communicate()

But then again, the approach you're using is flawed in several ways - you're delegating work to shell, when Python would do perfectly well. Also, on some computers the model name field might contain the word processor or a new field be added with that content, and your approach would be broken then, thus I'd suggest that you wrote the code in pure python instead:

cpus = 0
with open('/proc/cpuinfo') as f:
    for line in f:
        if line.partition(':')[0].strip() == 'processor':
            cpus += 1

Upvotes: 5

Related Questions