如何在没有终端提示的情况下从 IPython 会话中复制

Posted

技术标签:

【中文标题】如何在没有终端提示的情况下从 IPython 会话中复制【英文标题】:How to Copy from IPython session without terminal prompts 【发布时间】:2017-04-25 12:31:03 【问题描述】:

我的工作流程经常涉及到 IPython shell 中的数据清理/修改。自从 IPython 5.0 版和所有伟大的upgrades to the terminal interface 以来,这变得特别美妙。所以,假设我尝试整理一些非结构化数据:

In [11]: for i, (num, header, txt) in enumerate(data):
    ...:     header = [e.strip() for e in header.strip().split('\n')]
    ...:     header[4] = header[4].strip(',').split(',')
    ...:     data[i] = (num, header, txt)
    ...:

太棒了,它有效!但是现在,我真的很想将它添加到我的编辑器中的脚本中。如果我从终端复制和粘贴,我会捕获左侧的所有垃圾。我可以在编辑器中或多或少轻松地清理它,但如果我可以将代码从终端直接复制到我的剪贴板,而不用触摸鼠标,也不需要抓取额外的东西,那就太好了。 IPython中有这样的功能吗?

【问题讨论】:

Looks like people have implemented the feature,但它似乎没有随 IPython 一起提供。 如果你不想自定义你的 IPython 设置,print(In[11]) 应该给你一些可以复制的东西,而不是左边的垃圾。 @user2357112 嗯,虽然这并不理想,但这对我有用。如果您将其添加为答案,但没有更好的结果,我会接受。 不是这个问题的真正答案,但我倾向于做相反的事情——在 vim 中键入代码,然后使用 jupyter-vim 插件将代码发送到 jupyter 执行它。这样代码已经在vim中了,不需要复制。 @user202729 这不是关于 jupyter,而是关于 IPython REPL。重点是使用 REPL 进行实验。我一般不使用 Jupyter 笔记本。 【参考方案1】:

save 魔术命令 [documentation] 将您想要的输入行保存到文件中; -a 选项用于“追加”模式,以便将行添加到文件末尾而不是覆盖文件。我一直在用它。

用你的例子:

%save -a myfile.py 11
# the '%' is not necessary
save -a myfile.py 11

然后你可以继续在 IPython 中编码。

当有另一个命令要写入同一个文件时,您只需键入 save 然后使用向上箭头恢复上次使用的“保存”(以便 -a 选项和文件名已经在那里),只需编辑行号。

请注意,您可以提供几行来保存以及行范围:

save -a myfile.py 15 18 19-25

【讨论】:

我喜欢这个解决方案的地方是它还可以在 ipython shell 中显示没有终端提示的代码。【参考方案2】:

所以,我终于找到了一个很好的解决方案,基本上正是我想要的:在 IPython 中使用 Vi 模式。在版本 5 中,这需要:

$ ipython --TerminalInteractiveShell.editing_mode=vi

现在我可以使用方便的类似于 vi 的可视模式并拉出我需要的任何内容!

这会导致我的 .bash_profile/.bash_rc 中出现以下新别名:

alias vpython='ipython --TerminalInteractiveShell.editing_mode=vi'

【讨论】:

您可以将c.TerminalInteractiveShell.editing_mode = 'vi' 添加到~/.ipython/profile_default/ipython_config.py,而不是使用别名。感谢here,了解更多详情。 很好的答案,但仍然如何使用终端提示复制代码?? 拉到常规剪贴板功能在 IPython vim 模式下似乎不像在 Vim 中那样工作。 "+y 不起作用。【参考方案3】:

在 shell 中,您可以先将 IPython 文件转换为常规 Python 文件 (.py),然后进行清理:

http://ipython.org/ipython-doc/3/notebook/nbconvert.html(参见 --to 脚本格式)

您也可以在笔记本编辑器中将文件下载为 Python 文件,并在此步骤后执行清理。

【讨论】:

...我认为您不明白,没有 IPython 文件(我假设您的意思是 Jupyter 笔记本)。重点是我在终端中,使用 shell,理想情况下,我根本不想使用鼠标。 %history 魔法最接近,这就是我接受的原因,但不幸的是,它仍然需要鼠标。 是的,您是正确的 Jupyter 笔记本文件 (ipynb) 格式。我认为您可能能够在终端中运行以下类型的命令: $ ipython nbconvert --to script .ipynb 以创建一个可行的文件以在终端中进行清理(我很抱歉,刚从 Python 开始)TI 学会了来自你的帖子。 是的,不幸的是,我没有使用 jupyter 笔记本,我正在使用 REPL。有时我会这样做,但是由于您指出的工具以及代码已经采用清理后的文本格式这一事实,问题没有实际意义。 有趣的是,您以前将 REPL 称为 shell 或终端。对于 REPL 窗口中的代码,我的大多数编辑器允许我通过按住 shift - alt 键并使用箭头来复制矩形。在您的示例中,将光标放在 for 关键字的右侧。这适用于 Visual Studio、Atom、VIM 等。我一直从 REPL 复制到编辑器中没有问题。如果这对您很重要并且不能在您的 IDE/文本编辑器中工作,那么我建议您查看替代 IDE/文本编辑器。 但问题不在于我的 IDE,我不使用 IDE,我使用终端模拟器和文本编辑器,而编辑器无关紧要(我使用 vim,有时使用 Atom),但问题是从终端中的 REPL 会话复制【参考方案4】:

您可以使用%history 魔法从会话中提取有趣的部分。它们将显示在终端中,没有任何垃圾。

示例

In [1]: import numpy as np    
In [2]: a = np.random(10)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-2-83ce219ad17b> in <module>()
----> 1 a = np.random(10)

TypeError: 'module' object is not callable

In [3]: a = np.random.random(10)
In [4]: for i in a:
   ...:     print(i)
   ...:     
0.688626523886
[...]
0.341394850998

如果我想保存上面会话的一部分,我可以使用:

In [5]: %history 1 3-4

import numpy as np
a = np.random.random(10)
for i in a:
    print(i)

在上面的示例中,我使用%history 1 3-4 组合所有我想保留的命令并省略我不需要的命令(第 2 行,有错误的那个)。现在您有了可以很好地复制的会话版本。

写入文件

您也可以使用-f FILENAME 作为参数直接将其写入文件。

In [8]: %history 1 3-4 -f /tmp/foo.py

不过要小心,这会覆盖现有文件。 更多详情请见documentation of the %history magic。

【讨论】:

这是一个有用的功能,虽然它也给出了我们在输出中使用的命令,例如如果我使用%history,它下次也会给出。我认为这就是 history 所做的。【参考方案5】:

我不认为终端应用程序真的可以访问复制/粘贴缓冲区。你将不得不使用鼠标。怎么做取决于您使用的终端。大多数现代终端都有某种“矩形选择”或“块选择”模式。

对于 Windows,矩形选择是 cmd.exe 和 Powershell 的默认设置。如果您使用的是 Cygwin 的 mintty,请按住 Alt,然后用鼠标选择该区域。 PuTTY 也是如此。

在 Linux 上(我面前没有 - 对这些持保留态度),xterm 不支持它,Gnome 终端使用 Ctrl 作为修饰符,而 KDE 的Konsole 使用 Ctrl+Alt

对于 OS X 终端,互联网告诉我您在单击时使用了

其他终端(和 GNU Screen)可能具有该功能,只是弄清楚如何激活它。

【讨论】:

终端应用程序获得与任何其他应用程序相同的剪贴板访问权限。

以上是关于如何在没有终端提示的情况下从 IPython 会话中复制的主要内容,如果未能解决你的问题,请参考以下文章

在没有提示的情况下从 python-fabric 重置 mysql root 密码

如何在没有选择器的情况下从应用程序发送电子邮件? [复制]

linux终端里,退出后再次登录,如何找回上次离开时的软件状态(还原上次会话)?

在 IPython qtconsole 中确定终端宽度

如何在emacs中打开IPython解释器?

在没有抓取HTML的情况下从whattomine中的链接接收JSON数据