Why aren't there quotes in sys.argv when they were used at the command line?

Viewed 1574

Is this a bug?

#!/usr/bin/env python3.6
# filename: tmp.py
import sys

print(sys.argv)

Invoked:

python tmp.py find . -name '*.py'

Actual output:

['tmp.py', 'find', '.', '-name', '*.py']

Expected output:

['tmp.py', 'find', '.', '-name', "'*.py'"]

Note the lack of quotations within the actual output.

2 Answers

no, because your shell removes the quotes before passing the argument to python (else it would expand the *.py wildcard)

To get what you want you'd need:

python tmp.py find -name "'*.py'"

Note that this behaviour is shell dependent. On windows, since single quotes have no particular meaning, passing '*.py', you would get:

['tmp.py', 'find', '.', '-name', "'*.py'"]

Also note that quote-protected wildcards have no real interest on the python side, since you'd need to strip the quotes to be able to evaluate them with glob.glob

The shell is responsible for breaking down the command it's running into a list of C strings. Those strings are then passed to the program being run.

In the example:

python tmp.py find . -name '*.py'

...the argument list a correctly-implemented shell will generate for the argv element of the execve syscall would look (in C syntax) like:

char[][]{ "python", "tmp.py", "find", ".", "-name", "*.py", NULL }

When Python runs, it doesn't know what the original command was: It has no way of knowing if you typed '*.py' or \*.py or any other thing; it only sees the argument list the shell handed off to the operating system.

Related