[Tutor] Executing shell commands

Peter Otten __peter__ at web.de
Sun Feb 16 06:28:07 EST 2020


boB Stepp wrote:

> On Sat, Feb 15, 2020 at 9:46 PM Phil <phillor9 at gmail.com> wrote:
>>
>> On 16/2/20 12:47 pm, boB Stepp wrote:
>> Thank you Bob for your reply.
>> > subprocess.call("ls", "/home/phil/Downloads/*.gpx", shell=True)
>> Adding shell=True to .call() or .run() generates the following:
>>
>> Traceback (most recent call last):
>>    File "/home/phil/Python/waypoints.py", line 6, in <module>
>>      subprocess.run("ls", "/home/phil/Downloads/*.gpx", shell=True)
>>    File "/usr/lib/python3.7/subprocess.py", line 488, in run
>>      with Popen(*popenargs, **kwargs) as process:
>>    File "/usr/lib/python3.7/subprocess.py", line 702, in __init__
>>      raise TypeError("bufsize must be an integer")
>> TypeError: bufsize must be an integer
>>
>> Anyway, you've given me something to think about, I'll experiment
>> further.
> 
> Apparently your original approach of making a list of arguments is the
> correct one, and I was sadly mistaken.  You *do* need the square
> brackets.  Try that and hopefully all will be well.

There are basically two ways to invoke call():

(1) with a list and shell=False.

>>> from subprocess import call
>>> call(["ls", "*.py"], shell=False)
ls: cannot access *.py: No such file or directory
2

As the shell is not involved '*.py' is passed directly, and thus 'ls' will 
look for a file '*.py' which usually doesn't exist.

This is the best option as there's no need to consider argument escaping and 
shell injection. If you want wildcards you can emulate them in Python:

>>> import glob
>>> call(["ls"] + glob.glob("*.py"))
a.py  b.py  c.py
0

(2) with a string and shell=True.

>>> call("ls *.py", shell=True)
a.py  b.py  c.py
0

The shell will process the string according to its rules as if you had typed 
it on the command line, i. e. it will split args and expand wildcards and 
then issue a command equivalent to Python's 

call(["ls", "a.py", "b.py", "c.py"], shell=False)

This option may seem convenient, but can be a constant source of problems 
(filenames with spaces have to be escaped, user input has to be sanitized 
etc.) 

As has been mentioned in this thread glob and pathlib offer alternatives 
that are easier to control.

(3) Other combinations are usually a programming error.




More information about the Tutor mailing list