【问题标题】:Can I use IPython embed() to change the state of a function?我可以使用 IPython embed() 来更改函数的状态吗?
【发布时间】:2021-10-31 19:56:15
【问题描述】:

是否可以在函数中嵌入 IPython 会话,以便对代码进行更改,就好像它在全局命名空间中一样?如果不是,为什么?还有其他选择吗?

来自 IPython wiki 上关于 embedding an IPython session from the inside of a Python script 的条目:

请务必注意,在嵌入式 IPython shell 中运行的代码不会改变代码和变量的状态,除非 shell 包含在全局命名空间中。

这种行为的一个小例子是从 IPython 会话中更改变量,该会话位于 Python REPL 中:

>>> from IPython import embed
>>> a = 12
>>> embed()

In [1]: a = 13

In [2]: exit()

>>> a
13

但是当嵌入到函数中时:

>>> from IPython import embed
>>> def f():
...     x = 2
...     embed()
...     print(x)
... 
>>> f()

In [1]: x = 3

In [2]:                                                                  

2

虽然我不明白为什么必须这样(设计选择?技术问题?)我想在全局命名空间之外使用 IPython 更改我的代码,即一个函数,它应该是允许的行为,考虑到最好结构化程序将尽可能少地留给全局命名空间(在我的情况下,我正在尝试更改我的 main() 函数)。

【问题讨论】:

  • 它在文档中明确表示这是不可能的。你还问什么?
  • @smac89 你看到这部分了吗? “如果没有,为什么?还有其他选择吗?
  • 文档回答了 why 部分。如果您对此不满意,那么您可以查看源代码并向 ipython 人员进行 PR 以启用此功能。至于替代方案,我不知道;您正试图绕过明确定义的行为,因此任何解决方案都极有可能是 hack,并且可能无法 100% 发挥作用。
  • @smac89 它在文档中的什么地方说明了原因?我只看到它说不可能。

标签: python ipython


【解决方案1】:

请不要这样做!这只是一个关于如何破解此设计功能的 PoC。

您可能不会找到不涉及类似问题的解决方案。但我将把它留在这里,这样你就可以看到潜在的解决方法有多难看。

from IPython import embed

def main():
  global g
  g = 40
  embed()
  print (g)

main()

现在在 IPython repl 中,我们这样做了:

Python 3.9.2 (default, Feb 27 2021, 00:33:24)
Type 'copyright', 'credits' or 'license' for more information
IPython 7.19.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: g += 2

In [2]: globals().update(dict(g=g))

In [3]:

输出:

42

它不仅是 hacky,而且还涉及到全局命名空间,这在你看来是不可取的。

【讨论】:

  • 是的,我知道你在哪里,但不幸的是,这并不像在上面安装 embed() 那样简单,因为你必须事先猜测你想要修改哪些变量,并且它仍然只会修改全局命名空间。
猜你喜欢
  • 2021-01-21
  • 2021-04-15
  • 1970-01-01
  • 1970-01-01
  • 2017-09-04
  • 2020-08-19
  • 1970-01-01
  • 2021-10-03
  • 2019-10-16
相关资源
最近更新 更多