如何使调用者的命名空间可用于导入函数中 IPython 的魔法?

How to make caller's namespace available to IPython's magic inside imported function?

我正在尝试调用一个在 'timex.py' 中定义的小辅助函数,它是从 'caller.py' 调用的,它又应该从 (PyCharm's) IPython-控制台通过“%运行 caller.py”.

这目前导致 "NameError: name 'pickle' is not defined"。

# timex.py

from IPython import get_ipython

def time_expression(exp: str):    
    print(f"time expression: {exp}", flush=True)
    return get_ipython().magic(f"timeit {exp}")

# caller.py

import pickle
from timex import time_expression

packet = [*range(10**2)]
time_expression("pickle.dumps(packet, protocol=-1)")

# Then run from IPython-console:

>>>%run caller.py
time expression: pickle.dumps(packet, protocol=-1)
NameError: name 'pickle' is not defined

显然 ipython timeit-magic 的命名空间不包含 caller.py-全局变量。传递 globals() 作为 time_expression 的参数并从 time_expression 中更新全局变量没有帮助,传递 get_ipython() 作为参数也没有成功。

有没有办法让它起作用?

如果我在 caller.py 中定义 time_expression 并使用 "ipython caller.py" 从终端调用,它会起作用,但我更愿意将其放入库中,然后将其导入到需要的地方.

(Python 3.6.3, IPython 6.2.1)

好吧,看来我运气不错。 我在这里 link 发现了一个提示,即 shell 有一个 'user_ns' 参数。 更新此 user_ns-dictionary 然后使用调用者的本地人是使其适用于从 caller.py 到 运行ning %运行 caller.py 从 [=20] 导入的解决方案=] 控制台。

有点老套,我现在觉得很脏 ;) 也许有更优雅的方式?

import sys
from IPython import get_ipython

def time_expression(exp: str):
    """"""
    ipy = get_ipython()
    ipy.__dict__['user_ns'].update(sys._getframe(1).f_locals)
    print(f"time expression: {exp}", flush=True)
    return ipy.magic(f"timeit {exp}")