I’m a beginner in Python, and I’ve been trying to call a command line app, but it fails:
>>> import subprocess as s
>>> s.call("gpio -g read 17")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.6/subprocess.py", line 470, in call
return Popen(*popenargs, **kwargs).wait()
File "/usr/lib/python2.6/subprocess.py", line 623, in __init__
errread, errwrite)
File "/usr/lib/python2.6/subprocess.py", line 1141, in _execute_child
raise child_exception
OSError: [Errno 2] No such file or directory
But then if I add shell=True it all starts working. Can someone explain why?
>>> import subprocess as s
>>> s.call("gpio -g read 17", shell=True)
>>> 0
You’re not using call right. Look at the introduction or any of the examples in the docs. The first argument of call is “args”, a sequence of arguments, where arg[0] is the program to run.
So, when you do this:
There are two ways subprocess could interpret this. It should run a program called “g” with arguments “p”, “i”, “o”, ” “, etc. (Remember, strings are sequences of characters.) It might instead run a program called “gpio -g read 17” with no additional arguments. Either way, it’s not going to find such a program. (Unless you happen to have a program called “g” or “gpio -g read 17” on your PATH, in which case it’ll do the wrong thing instead of giving you an error…)
What you want is:
So, why does this work if you pass
shell=True? Because this whole string gets passed to the shell, which then does its own parsing of the command line and separates things by spaces. It’s like callingos.system("gpio -g read 17").Please note that all of the above is a bit oversimplified (it ignores Windows, and shell parsing isn’t really just “separate by spaces”, and so on), so you should actually read the documentation. (Also, whoever wrote the
subprocessdocs is a better writer than me.)