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 行函数是最佳解决方案。如果您能提出更正确的方法,我将不胜感激。
请记住:
- 我正在寻找一种也可以在脚本和函数中运行的解决方案。
- 我知道有 "pickle" 但我拒绝为像简单的 'save' and/or 'load' 命令这样平凡的东西使用多行代码。
- 我知道 scipy 提供 "savemat" 和 "loadmat",但我想完全迁移,即不使用 mat 文件,而是使用 numpy 数组。
在此先感谢您的帮助。
[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
适用于交互式使用,但不适用于脚本
自
- 它使文件能够重新绑定任意名称
任意值。这可能会导致令人惊讶的、难以调试的行为,甚至是安全风险。
- 动态创建的变量名很难编程。作为
Python (
import this
) 的 Zen 说,“命名空间是一个喇叭
好主意——让我们做更多这样的事情!”对于脚本来说,最好是
将值保留在 NpzFile
、f
中,并通过索引访问它们,
比如f['x']
.
我正在从 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 行函数是最佳解决方案。如果您能提出更正确的方法,我将不胜感激。
请记住:
- 我正在寻找一种也可以在脚本和函数中运行的解决方案。
- 我知道有 "pickle" 但我拒绝为像简单的 'save' and/or 'load' 命令这样平凡的东西使用多行代码。
- 我知道 scipy 提供 "savemat" 和 "loadmat",但我想完全迁移,即不使用 mat 文件,而是使用 numpy 数组。
在此先感谢您的帮助。
[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
适用于交互式使用,但不适用于脚本
自
- 它使文件能够重新绑定任意名称 任意值。这可能会导致令人惊讶的、难以调试的行为,甚至是安全风险。
- 动态创建的变量名很难编程。作为
Python (
import this
) 的 Zen 说,“命名空间是一个喇叭 好主意——让我们做更多这样的事情!”对于脚本来说,最好是 将值保留在NpzFile
、f
中,并通过索引访问它们, 比如f['x']
.