Chapter 16 ■ telnet and SSh
293
$ python shell.py
] echo Hi there!
Hi there!
] echo An asterisk is not special.
An asterisk is not special.
] echo The string $HOST is not special, nor are "double quotes".
The string $HOST is not special, nor are "double quotes".
] echo What? No <>!$ special characters?
What? No <>!$ special characters?
] show "The 'show' built-in lists its arguments."
Arguments: ['"The', "'show'", 'built-in', 'lists', 'its', 'arguments."']
] exit
You can see absolute evidence here that Unix commands—in this case, the /bin/echo command that you are
calling over and over again—pay no attention to special characters in their arguments. The echo command happily
accepts characters like double quotes, dollar signs, and asterisks inside its argument list and treats them all as literal
characters. As the foregoing show command illustrates, Python is simply reducing your arguments to a list of strings
for the operating system to use in creating a new process.
What if you fail to split your command into separate arguments and pass a command name and argument to the
operating system as a single string?
import subprocess
subprocess.call(['echo hello'])
Traceback (most recent call last):
...
FileNotFoundError: [Errno 2] No such file or directory: 'echo hello'
Do you see what has happened? The operating system does not know that spaces should be special. Thus, the
system thinks that it is being asked to run a command literally named echo[space]hello, and unless you have created
such a file in the current directory, it fails to find it and raises an exception.
There is one single character that is, in fact, special to the system: the null character (the character having the
Unicode and ASCII code zero). The null character is used in Unix-like systems to mark the end of each command-line
argument in memory. Thus, if you try using a null character in an argument, Unix will think the argument has ended,
and it will ignore the rest of its text. To prevent you from making this mistake, Python stops you in your tracks if you
include a null character in a command-line argument.
subprocess.call(['echo', 'Sentences can end\0 abruptly.'])
Traceback (most recent call last):
...
TypeError: embedded NUL character
Happily, since every command on the system is designed to live within this limitation, you will generally find
that there is never any reason to put null characters into command-line arguments anyway. (Specifically, they
cannot appear in file names for exactly the same reason they cannot appear in argument lists: the operating system is
supplied with file names in null-terminated strings.)