从python执行bash命令 - OSError:[Errno 2]

0 python subprocess python-2.7

我是Python的新手.当我执行以下命令以使用以下python代码获取我的x86服务器上的总CPU核心数时,我得到如下错误;

########################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
Run Code Online (Sandbox Code Playgroud)

os.popen工作,但我不想使用,os.popen因为它打印None在我要省略的总核心数的末尾/

Ant*_*ala 6

首先,子进程|在命令中不会理解,或者通常在shell中运行命令,除非shell=True提供.相反,您的程序将尝试查找命令/usr/bin/cat\ /proc/cpuinfo\ \|\ grep\ -i\ processor\ \|\ wc\ -l,当然这会失败.

解决方案是添加shell=True以在shell中执行命令:

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

但是,也可以在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()
Run Code Online (Sandbox Code Playgroud)

但话说回来,你使用的方法在几个方面存在缺陷 - 你将工作委托给shell,当python做得非常好时.此外,在某些计算机上,该model name字段可能包含该单词processor或添加了该内容的新字段,然后您的方法将被破坏,因此我建议您使用纯python编写代码:

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

但是这一切都没用,因为Python已经知道你有多少CPU,并且这可以保证比你提出的任何bash命令更便携:

>>> import multiprocessing
>>> multiprocessing.cpu_count()
4
Run Code Online (Sandbox Code Playgroud)