如何将IPython历史记录记录到文本文件?

48

经过搜索和查看IPython的documentation和一些code后,我似乎无法弄清楚是否可以将命令历史记录(而不是输出日志)存储到文本文件而不是SQLite数据库中。 ipython --help-all似乎表明此选项不存在。

这对于版本控制频繁使用的命令非常有用,就像在.bash_history中一样。

编辑:基于@minrk的答案,Working solution已经可行。

5个回答

101
你可以使用 %history 魔法命令将IPython的所有历史记录导出到文本文件中,如下所示:
%history -g -f filename

要实现你想要的目标,一种方法是在Git钩子中执行导出操作。我通常会将这些“同步外部资源”的操作放在post-checkout Git钩子中。


6
运行 ?%history 命令还可以展示如何提取日志的特定部分,比如活动会话。 - Anton Tarasenko
这是最直接和简洁的答案。这应该是首选答案。 - Rich Lysakowski PhD
1
我只需要 history -g - Aaron Swan

16

您还可以选择想要保存的行。例如:

%history 1 7-8 10 -f /tmp/bar.py

这将把第1行、第7至8行和第10行保存到一个名为bar.py的临时文件中。如果需要完整内容,只需跳过这些行即可。

%history -f /tmp/foo.py

11

保存Ipython会话历史记录:

%save [filename] [line start - line end] 

例如:
%save ~/Desktop/Ipython_session.txt 1-31

这只会保存特定的IPython会话历史,但不会保存整个IPython命令历史记录。


9
您可以通过将以下内容添加到其中一个启动脚本(例如:$(ipython locate profile)/startup/log_history.py)中来模拟bash的行为:
import atexit
import os

ip = get_ipython()
LIMIT = 1000 # limit the size of the history

def save_history():
    """save the IPython history to a plaintext file"""
    histfile = os.path.join(ip.profile_dir.location, "history.txt")
    print("Saving plaintext history to %s" % histfile)
    lines = []
    # get previous lines
    # this is only necessary because we truncate the history,
    # otherwise we chould just open with mode='a'
    if os.path.exists(histfile):
        with open(histfile, 'r') as f:
            lines = f.readlines()

    # add any new lines from this session
    lines.extend(record[2] + '\n' for record in ip.history_manager.get_range())

    with open(histfile, 'w') as f:
        # limit to LIMIT entries
        f.writelines(lines[-LIMIT:])

# do the save at exit
atexit.register(save_history)

请注意,这个功能模拟了bash/readline历史记录的行为,如果解释器崩溃等情况会失败。 在gist中查看 更新:替代方案
如果您只想让readline(自动补全、^R搜索等)可用几个手动收藏的命令,并且可以进行版本控制,那么这个启动文件将允许您自己维护该文件,该文件仅是IPython实际命令历史记录的补充。
import os

ip = get_ipython()

favfile = "readline_favorites"

def load_readline_favorites():
    """load profile_dir/readline_favorites into the readline history"""
    path = os.path.join(ip.profile_dir.location, favfile)
    if not os.path.exists(path):
        return

    with open(path) as f:
        for line in f:
            ip.readline.add_history(line.rstrip('\n'))

if ip.has_readline:
    load_readline_favorites()

将此文件放入您的profile_default/startup/目录中,并编辑profile_default/readline_favorites或您喜欢的任何其他位置,它将显示在每个IPython会话的读取行完成等中。

现在我感到困惑 - 这样,文件是从“真正”的历史记录中编写的,因此这些命令将始终是您实际历史记录中最近的。 - minrk
如果你真的只想要一个始终在你的readline历史记录中的流行命令文件,那么可能有比使用IPython历史记录更好的方法。我更新了我的答案,包括一个示例,该示例从收藏夹文件中填充readline历史记录,但严格来说是作为真实历史记录的补充。 - minrk

0
使用纯文本文件来存储历史记录会导致不同会话的命令交错,还会使得像“从会话x运行第三条命令”或者搜索历史记录等功能变得过于复杂和缓慢。因此采用sqlite数据库。
不过,编写一个脚本将历史记录转储到文件并同时进行统计应该非常容易。你可以通过sqlite做到所有文本文件所能做的事情。

1
它在Bash中非常有效,即使每次执行命令时读取数千行历史记录。就我个人而言,除非有一些我从未使用过的花哨会话处理方式,否则我不会对几个会话之前运行的命令有任何想法。但我不仅想要历史记录的转储,而是用一个有用的功能替换当前的功能(对我来说几乎没有用处)。 - l0b0
你以前是将历史记录存储到文本文件中,还是一直使用数据库?如果是前者,我可以轻松地利用它进行分支。 - l0b0
它曾经是一个文本文件,但自那时以来代码已经发生了很大变化,所以我不建议去翻旧账。 - Thomas K

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接