The !
escape runs an external shell command, like ping -c 3 www.google.com
, not a Python command. Python or ipython
has no idea what ping
does, it just passes over control to it, and displays its output.
The %
escape runs an ipython
built-in command or extension, i.e. something that ipython
itself understands.
To quote the documentation,
User-extensible ‘magic’ commands. A set of commands prefixed with %
or %%
is available for controlling IPython itself and provides directory control, namespace information and many aliases to common system shell commands.
The source of confusion here is probably that e.g. ls
is also available as a "magic" command for portability and convenience. (It's portable in that it works even on platforms where there is no system ls
command, like Windows.)