The text is released under the CC-BY-NC-ND license, and code is released under the MIT license. If you find this content useful, please consider supporting the work by buying the book!
当与标准 Python 解释器交互工作时,其中一个缺点是需要在多个窗口之间切换以访问 Python 和命令行工具。IPython 解决了这个问题,它为你提供了直接在 IPython 中执行 shell 命令的语法。魔法源于感叹号:在 !
出现的行中,其后面的任何内容都不会被 Python 执行,而是由系统命令行执行。
下面的示例假设你使用类 Unix 的操作系统,例如 Linux 或 Mac OSX。下面的一些示例将在 Windows 上失败,Windows 在默认情况下使用不同类型的 shell(不过 Windows 上发布了原生的 Bash shell,在很快将不再是问题!)如果你不熟悉 shell 命令,我建议查看 Software Carpentry Foundation 编纂的Shell教程 。
When working interactively with the standard Python interpreter, one of the frustrations is the need to switch between multiple windows to access Python tools and system command-line tools.
IPython bridges this gap, and gives you a syntax for executing shell commands directly from within the IPython terminal.
The magic happens with the exclamation point: anything appearing after !
on a line will be executed not by the Python kernel, but by the system command-line.
The following assumes you're on a Unix-like system, such as Linux or Mac OSX. Some of the examples that follow will fail on Windows, which uses a different type of shell by default (though with the 2016 announcement of native Bash shells on Windows, soon this may no longer be an issue!). If you're unfamiliar with shell commands, I'd suggest reviewing the Shell Tutorial put together by the always excellent Software Carpentry Foundation.
介绍使用 shell/终端/命令行的完整内容远远超出了本章节的范围,但对于初学者我们可以有一些简单的介绍。shell 是与计算机进行文本交互的方式。20二十世纪八十年代中期微软和苹果相继发布了自己的图像操作系统,大多数计算机用户通过点击和拖拽和他们的操作系统交互。但是操作系统早在图像界面出现前就有了,那时候是主要通过文本输入与其交互的:用户在交互窗输入命令然后计算机执行它。这些早期的系统是现在这些数据科学家使用的 shell 和终端的前身。
A full intro to using the shell/terminal/command-line is well beyond the scope of this chapter, but for the uninitiated we will offer a quick introduction here. The shell is a way to interact textually with your computer. Ever since the mid 1980s, when Microsoft and Apple introduced the first versions of their now ubiquitous graphical operating systems, most computer users have interacted with their operating system through familiar clicking of menus and drag-and-drop movements. But operating systems existed long before these graphical user interfaces, and were primarily controlled through sequences of text input: at the prompt, the user would type a command, and the computer would do what the user told it to. Those early prompt systems are the precursors of the shells and terminals that most active data scientists still use today.
不熟悉 shell 的人可能会问为什么你会用这个,现在很多命令可以通过点击图标和菜单完成了呀。shell 用户可能回答另一个问题:对于可以通过输入更容易完成的事情,为什么用图标和菜单?它可能听起来像一个典型的技术癖好,但对于那些复杂的命令来说 shell 提供了更多的高级控制方式,虽然不可否认,这种方式的学习曲线会吓倒一般的计算机用户。
Someone unfamiliar with the shell might ask why you would bother with this, when many results can be accomplished by simply clicking on icons and menus. A shell user might reply with another question: why hunt icons and click menus when you can accomplish things much more easily by typing? While it might sound like a typical tech preference impasse, when moving beyond basic tasks it quickly becomes clear that the shell offers much more control of advanced tasks, though admittedly the learning curve can intimidate the average computer user.
举个例子,下面是一个 Linux / OSX shell 会话的示例,其中用户在其系统上探索,创建和修改目录和文件(osx:~ $
是提示符,$
后的所有内容都是输入的命令;#
后的内容只作为解释,不是你实际输入的东西):
As an example, here is a sample of a Linux/OSX shell session where a user explores, creates, and modifies directories and files on their system (osx:~ $
is the prompt, and everything after the $
sign is the typed command; text that is preceded by a #
is meant just as description, rather than something you would actually type in):
osx:~ $ echo "hello world" # echo is like Python's print function
hello world
osx:~ $ pwd # pwd = print working directory
/home/jake # this is the "path" that we're sitting in
osx:~ $ ls # ls = list working directory contents
notebooks projects
osx:~ $ cd projects/ # cd = change directory
osx:projects $ pwd
/home/jake/projects
osx:projects $ ls
datasci_book mpld3 myproject.txt
osx:projects $ mkdir myproject # mkdir = make new directory
osx:projects $ cd myproject/
osx:myproject $ mv ../myproject.txt ./ # mv = move file. Here we're moving the
# file myproject.txt from one directory
# up (../) to the current directory (./)
osx:myproject $ ls
myproject.txt
这里展示了通过输入命令而不是点击图标和菜单来进行常见的操作(目录导航,创建目录,移动文件等)。只要几个命令(pwd,ls,cd,mkdir,和 cp),你就可以做很多最常见的文件操作。如果你在此基础上更进一步,你会发现 shell 真的非常强大。
Notice that all of this is just a compact way to do familiar operations (navigating a directory structure, creating a directory, moving a file, etc.) by typing commands rather than clicking icons and menus.
Note that with just a few commands (pwd
, ls
, cd
, mkdir
, and cp
) you can do many of the most common file operations.
It's when you go beyond these basics that the shell approach becomes really powerful.
任何在 shell 中的命令都可以在 IPython
中加个 !
执行。比如 ls
pwd
echo
可以这么执行:
Any command that works at the command-line can be used in IPython by prefixing it with the !
character.
For example, the ls
, pwd
, and echo
commands can be run as follows:
In [1]: !ls
myproject.txt
In [2]: !pwd
/home/jake/projects/myproject
In [3]: !echo "printing from the shell"
printing from the shell
Shell 命令不仅仅可以在 IPython 中被调用,也能与 IPython 进行其他交互。比如你可以把 shell 命令的执行结果保存到 Python 列表中:
Shell commands can not only be called from IPython, but can also be made to interact with the IPython namespace. For example, you can save the output of any shell command to a Python list using the assignment operator:
In [4]: contents = !ls
In [5]: print(contents)
['myproject.txt']
In [6]: directory = !pwd
In [7]: print(directory)
['/Users/jakevdp/notebooks/tmp/myproject']
注意返回的结果不是真正的 list 类型,而是 IPython 为 shell 返回值创建的特殊类型:
Note that these results are not returned as lists, but as a special shell return type defined in IPython:
In [8]: type(directory)
IPython.utils.text.SList
它们的行为和 Python 的 list 基本一致,但是会有一些额外的功能,比如可以使用 grep
和 fields
方法,s
n
p
属性允许你更方便的搜索、过滤和展示结果。更多信息可以在 IPython 的内建帮助中找得到。
This looks and acts a lot like a Python list, but has additional functionality, such as
the grep
and fields
methods and the s
, n
, and p
properties that allow you to search, filter, and display the results in convenient ways.
For more information on these, you can use IPython's built-in help features.
反过来,把 Python 变量传递给 shell 命令可以通过 {varname}
这样的语法做得到:
Communication in the other direction–passing Python variables into the shell–is possible using the {varname}
syntax:
In [9]: message = "hello from Python"
In [10]: !echo {message}
hello from Python
用大括号包裹变量名的语法会被解析为变量的内容并传递给 shell 命令。
The curly braces contain the variable name, which is replaced by the variable's contents in the shell command.
如果你已经用了一段时间 IPython 和 shell 的交互方式你可能发现了 !cd
不能在 IPython 中使用的情况:
If you play with IPython's shell commands for a while, you might notice that you cannot use !cd
to navigate the filesystem:
In [11]: !pwd
/home/jake/projects/myproject
In [12]: !cd ..
In [13]: !pwd
/home/jake/projects/myproject
因为 notebook 中的 shell 命令是在一个临时的子 shell 中执行的。如果你想要更改当前的工作目录需要 %cd
命令:
The reason is that shell commands in the notebook are executed in a temporary subshell.
If you'd like to change the working directory in a more enduring way, you can use the %cd
magic command:
In [14]: %cd ..
/home/jake/projects
实际上你不写 %
也可以:
In fact, by default you can even use this without the %
sign:
In [15]: cd myproject
/home/jake/projects/myproject
```,
这被称为 ``automagic``(默认魔法函数),它可以用 ``%automagic`` 控制它的开关。除了 ``%cd`` 还有一些其他的 shell 的魔法命令:``%cat`` ``%cp`` ``%env`` ``%ls`` ``%man`` ``%mkdir`` ``%more`` ``%mv`` ``%pwd`` ``%rm`` 以及 ``%rmdir``,这些命令在 ``automagic`` 是开的状态下都可以不写 ``%`` 直接执行。这让 IPython 看起来就像是普通 shell 一样:
This is known as an ``automagic`` function, and this behavior can be toggled with the ``%automagic`` magic function.
Besides ``%cd``, other available shell-like magic functions are ``%cat``, ``%cp``, ``%env``, ``%ls``, ``%man``, ``%mkdir``, ``%more``, ``%mv``, ``%pwd``, ``%rm``, and ``%rmdir``, any of which can be used without the ``%`` sign if ``automagic`` is on.
This makes it so that you can almost treat the IPython prompt as if it's a normal shell:
```ipython
In [16]: mkdir tmp
In [17]: ls
myproject.txt tmp/
In [18]: cp myproject.txt tmp/
In [19]: ls tmp
myproject.txt
In [20]: rm -r tmp
z
这种从 Python 会话的同一终端窗口内访问shell意味着在编写Python代码时,在解释器和 shell 之间来回切换很少。
This access to the shell from within the same terminal window as your Python session means that there is a lot less switching back and forth between interpreter and shell as you write your Python code.