【问题标题】:Save workspace in IPython在 IPython 中保存工作区
【发布时间】:2014-09-29 18:54:31
【问题描述】:

是否可以保存 IPython 工作区(定义的函数、不同类型的变量等)以便以后加载?

这将是一个类似于 MATLAB 或 R 中的save.image() 的函数。之前已经提出过类似的问题,例如:

Save session in IPython like in MATLAB?

然而,几年过去了,我想知道现在是否有一个好的解决方案。

【问题讨论】:

  • 否,但您可以保存变量集。也许更好的办法是以笔记本的形式进行 ipythoning,结果、代码、可视化和 cmets 并排存在。
  • 看看%store魔术
  • %store 魔法似乎是一个可以接受的解决方案。至少它适用于 numpy 数组和 pandas DataFrame,这是我使用的大部分数据结构。有没有办法在 ipython 笔记本中自动执行此操作,类似于 Rstudio 所做的?
  • dill 包有一个dump_session() 函数,它将交互式会话的内容保存到文件中,包括一些pickle 无法正常处理的内容。我相当确定这适用于 IPython。您可以write an extension 在您关闭内核时自动执行此操作。

标签: python ipython


【解决方案1】:

您可以使用dill python 包:

import dill                            
filepath = 'session.pkl'
dill.dump_session(filepath) # Save the session
dill.load_session(filepath) # Load the session

要安装它:

pip install dill

【讨论】:

  • 无法使用 shell_plus 在 Django 项目中腌制“sqlite3.Connection”对象。
【解决方案2】:

编辑:这个答案(和gist)已被修改为适用于 IPython 6

我添加了一个有点特别的解决方案,该解决方案使用来自 IPython 的 %store 魔术的底层代码自动存储/恢复用户空间变量的过程,这是我理解你想要的。请参阅要点here。请注意,这只适用于可以腌制的对象。

我不能保证它的健壮性,尤其是如果 IPython 中的任何自动恢复机制在未来发生变化,但它一直适用于 IPython 2.1.0。希望这至少会为您指明正确的方向。

在这里重申解决方案:

  1. 将下面的 save_user_variables.py 脚本添加到您的 ipython 文件夹(默认为 $HOME/.ipython)。此脚本负责在退出时保存用户变量。
  2. 将此行添加到您的配置文件的 ipython 启动脚本(例如,$HOME/.ipython/profile_default/startup/startup.py):

    get_ipython().ex("import save_user_variables;del save_user_variables")

  3. 在您的 ipython 配置文件配置文件(默认为 $HOME/.ipython/profile_default/ipython_config.py)中找到以下行:

    # c.StoreMagics.autorestore = False

    取消注释并将其设置为 true。这会在启动时自动重新加载存储的变量。或者,您可以使用 %store -r 手动重新加载最后一个会话。

save_user_variables.py

def get_response(quest,default=None,opts=('y','n'),please=None,fmt=None):
    try:
        raw_input = input
    except NameError:
        pass
    quest += " ("
    quest += "/".join(['['+o+']' if o==default else o for o in opts])
    quest += "): "

    if default is not None: opts = list(opts)+['']
    if please is None: please = quest
    if fmt is None: fmt = lambda x: x

    rin = input(quest)
    while fmt(rin) not in opts: rin = input(please)

    return default if default is not None and rin == '' else fmt(rin)

def get_user_vars():
    """
    Get variables in user namespace (ripped directly from ipython namespace
    magic code)
    """
    import IPython
    ip = IPython.get_ipython()    
    user_ns = ip.user_ns
    user_ns_hidden = ip.user_ns_hidden
    nonmatching = object()
    var_hist = [ i for i in user_ns
                 if not i.startswith('_') \
                 and (user_ns[i] is not user_ns_hidden.get(i, nonmatching)) ]
    return var_hist

def shutdown_logger():
    """
    Prompts for saving the current session during shutdown
    """
    import IPython, pickle
    var_hist = get_user_vars()
    ip = IPython.get_ipython()
    db = ip.db

    # collect any variables that need to be deleted from db
    keys = map(lambda x: x.split('/')[1], db.keys('autorestore/*'))
    todel = set(keys).difference(ip.user_ns)
    changed = [db[k] != ip.user_ns[k.split('/')[1]]
               for k in db.keys('autorestore/*') if k.split('/')[1] in ip.user_ns]

    try:
        if len(var_hist) == 0 and len(todel) == 0 and not any(changed): return
        if get_response("Save session?", 'n', fmt=str.lower) == 'n': return
    except KeyboardInterrupt:
        return

    # Save interactive variables (ignore unsaveable ones)
    for name in var_hist:
        obj = ip.user_ns[name]
        try:
            db[ 'autorestore/' + name ] = obj
        except pickle.PicklingError:
            print("Could not store variable '%s'. Skipping..." % name)
            del db[ 'autorestore/' + name ]

    # Remove any previously stored variables that were deleted in this session
    for k in todel:
        del db['autorestore/'+k]

import atexit
atexit.register(shutdown_logger)
del atexit

【讨论】:

  • 有其他人在 Ipython 6 和 Windows 中尝试过这个吗?
  • 它对我不起作用..也许自 ipython 2.0 以来发生了一些变化
【解决方案3】:

虽然不如save.image() 方便,但您可以使用其中一种检查点/恢复应用程序。如果你使用的是 Linux,你可以试试http://criu.org。我不时使用它来转储我的ipython 状态并在以后恢复它。

为了使用 CRIU 转储 shell 应用程序,您需要找到它的 PID(例如 pstree -p),然后使用类似的东西(为此您需要第二个终端;CRIU 不能转储停止的作业) :

sudo criu dump -t PID --images-dir ~/tmp/imgs --log-file dump.log -v4 --shell-job

这会将所有必要的图像写入 ~/tmp/imgs(记住--shell-job 选项)。为了稍后将状态恢复到当前终端(不要忘记按回车以获取下一个ipython 提示):

sudo criu restore --images-dir ~/tmp/imgs/ --log-file restore.log -v4 --shell-job

如果有任何问题,请查看日志。

显然,CRIU 可以与任何应用程序一起使用(当然,有一些限制)。这只是一个想法,因此您可以将其用于ipython

【讨论】:

【解决方案4】:

你可以试试

%save name lines

如果你输入了 67 个命令并且你想保存所有命令:

%save myhistory 1-67

【讨论】:

  • 这是否真的保存了状态(即变量/对象)?我的理解是没有。如果有,你能举个例子吗?谢谢!
  • %save 会将历史命令保存到 .py 文件中。然后,我可以随时运行这个 .py 文件来恢复工作空间。 ` 在 [1] 中:s = '你好吗?'在 [2] 中:a = 123 在 [3] 中:%save x 1-2 以下命令被写入文件x.py:s = '你好吗?' a = 123`
  • @maoyang 不好的一点是重新运行命令可能需要很长时间
  • 我认为 OP 是在询问是否保存变量和工作区,而不是历史记录。历史记录会自动保存在 ipython 中,并且可以轻松检索。工作区并非如此。
【解决方案5】:

您当然可以在 ipython notebook 中执行此操作。

当笔记本保存——手动或默认配置——笔记本被保存为 .ipynb 文件,它只是一个 json 文件(github 要点中的 example)。

下次在该文件所在的目录中启动 ipython 服务器时,服务器会检测到它。

当您在浏览器中打开该笔记本时,所有代码和配置都在那里,但 未执行;您可以通过从单元格菜单中选择执行所有单元格来执行每个单元格中的代码。

此外,您可以手动将笔记本的快照保存为 ipynb_checkpoints,这些快照存储在以点开头的同名目录中。

最后,从 file 菜单选项中,您可以将笔记本保存为纯 Python 源文件 (.py)

【讨论】:

  • 谢谢,但这不是我想要的。我需要的是保留会话的状态(所有变量值)。这相当于 R 的 save.image() 函数。
  • @qkhhly 这就是我的回答:倒数第二句话,'ipynb_checkpoints';在此目录中加载文件,然后手动执行单元格中的代码或通过从菜单栏中的“单元格”中选择“全部执行”。
  • @doug,执行代码(再次)可能非常不切实际,例如这可能需要几个小时,所以它并不总是一个可行的解决方案。
  • 投反对票,因为这不是 OP 所要求的——不是重新运行所有内容的能力,而是恢复它们的状态“这将是类似于 MATLAB 或 R 中的 save.image() 的函数。”
  • 我发现这个回应有很多否定,但我认为其余的否定投票是级联的。 Doug 说你可以运行你想要的单元,所以......没有必要再次重新运行所有单元。您可以从快照开始执行。这个答案是正确的,并且由于级联效应而被否决。其他选民:请仔细阅读此解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多