IPython 将变量加载到工作区:你能想到比这更好的解决方案吗?

IPython loading variables to workspace: can you think of a better solution than this?

我正在从 MATLAB 迁移到 ipython,在迈出这一步之前,我将通过我的最小工作流程来确保我每天在 MATLAB 上为数据 c运行ching 执行的每项操作都是ipython 可用。

我目前坚持通过单行命令保存和加载 numpy 数组这一非常基本的任务,例如 MATLAB 的命令:

>>> save('myresults.mat','a','b','c')
>>> load('myresults.mat')

特别是,我喜欢 MATLAB 的加载命令,因为它不仅读取 数据文件,但它将变量加载到工作区中,不需要其他任何东西来开始使用它们。请注意,例如 numpy.load() 不是这种情况,它需要另一行才能将加载的值分配给工作区变量。 [参见:]

基于对那个问题的回答和评论,我想出了这个肮脏的、糟糕的、丑陋的、丑陋的、但可以工作的解决方案。我知道它不漂亮,我想知道您是否可以想出这个 [1] 的正确版本。

我把这个写成iocustom.py:

def load(filename):
    ip = get_ipython()
    ip.ex("import numpy as np")
    ip.ex("locals().update(np.load('" + filename + "'))") 

这样我就可以 运行,来自 ipython 会话:

import iocustom
load('myresults.npz')

并且变量被转储到工作区。

我很难相信没有与此等效的内置函数,更难以认为 3 行函数是最佳解决方案。如果您能提出更正确的方法,我将不胜感激。

请记住:

在此先感谢您的帮助。

[1] 顺便说一句:使用 ipython 的人如何轻松地保存和加载一组 numpy 数组?经过几个小时的谷歌搜索,我似乎无法为这项日常任务找到一个简单直接的解决方案。

如果我将其保存为 load_on_run.py:

import argparse
import numpy as np
if __name__=='__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('-l','--list', help='list variables', action='store_true')
    parser.add_argument('filename')
    __args = parser.parse_args()
    data = np.load(__args.filename)
    locals().update(data)
    del parser, data, argparse, np
    if __args.list:
        print([k for k in locals() if not k.startswith('__')])
    del __args

然后在 ipython 我可以用 %run:

调用它
In [384]: %run load_on_run testarrays.npz -l
['array2', 'array3', 'array4', 'array1']
In [385]: array3
Out[385]: array([-10,  -9,  -8,  -7,  -6,  -5,  -4,  -3,  -2,  -1])

它巧妙地将文件中的数组加载到 ipython 工作区。

我正在利用 magic %run 运行脚本这一事实,将它定义的所有函数和变量留在主命名空间中。我还没有研究它是如何做到这一点的。

该脚本只需要几个参数,加载文件(目前只有 .npz),并使用 locals().update 技巧将其变量放入本地命名空间。然后我清除掉不需要的变量和模块,只留下新加载的。

我或许可以为 %run load_on_run 定义一个别名。

我也可以想象这样一个脚本,它可以让您通过导入加载变量:from <script> import *

您可以将 npz 文件中的值分配给全局变量:

import numpy as np

def spill(filename):
    f = np.load(filename)
    for key, val in f.iteritems():
        globals()[key] = val
    f.close()

此解决方案适用于 Python2 和 Python3,以及任何形式的交互式 shell, 不只是 IPython。使用 spill 适用于交互式使用,但不适用于脚本 自

  1. 它使文件能够重新绑定任意名称 任意值。这可能会导致令人惊讶的、难以调试的行为,甚至是安全风险。
  2. 动态创建的变量名很难编程。作为 Python (import this) 的 Zen 说,“命名空间是一个喇叭 好主意——让我们做更多这样的事情!”对于脚本来说,最好是 将值保留在 NpzFilef 中,并通过索引访问它们, 比如f['x'].