原始启动板错误399627: https ://bugs.launchpad.net/ipython/+bug/399627
报告人:h-fangohr(Hans Fangohr)。
该错误可以重现如下:
fangohr<strong i="11">@eta</strong>:~$ python
Python 2.4.3 (#1, Jun 8 2009, 14:09:06)
[GCC 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from IPython.Shell import IPShellEmbed
>>> ipshell=IPShellEmbed()
>>> ipshell()
在刚开始的ipython会话中,全局变量有时不可见。 两个示例是:
范例1:
In [1]: a=1
In [2]: def f(x):
...: return a*x
...:
In [3]: f(2)
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
/home/fangohr/<ipython console>
/home/fangohr/<ipython console> in f(x)
NameError: global name 'a' is not defined
范例2:
In [4]: b=1
In [5]: (lambda :b)()
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
/home/fangohr/<ipython console>
/home/fangohr/<ipython console> in <lambda>()
NameError: global name 'b' is not defined
如果在脚本中放入“ b = 1;(lambda:b)()”,则没有错误,并且该脚本使用ipython的“ run”命令执行。
如果启动ipython之后以交互方式执行“ b = 1;(lambda:b)()”,则没有错误。
出现该错误的唯一方法是,如果从Python提示符下启动了嵌入式IPython shell,并且在提示符下以交互方式执行命令。
我在尝试使用python2.4的ipython-0.9.1时发现了相同的错误。
该错误由Olivier Klein报告给了nmag小组(http://nmag.soton.ac.uk)。
[LP评论1,作者:Fernando Perez,在2010-04-25 23:36:38.673176 + 00:00]
好的,我可以确认问题(即使在后备箱上),但是很难。 我现在只是确保已确认此错误,因此我们会继续对其进行跟踪,但是我不确定如何修复它。
问题在于,在嵌入式外壳程序中,我们尝试更新全局名称空间以使用周围的范围(这是嵌入式外壳程序的关键,以便能够看到您周围的内容)。 但是,这会导致在定义嵌套事物(例如本地函数)时,python无法解析ipython交互式名称空间。 有关详细信息,请参见嵌入式外壳程序的mainloop()方法。
我需要更多地思考如何解决这一问题,非常欢迎任何想法。
在启动板...
主席K在20小时前写道:
我也是。 除功能外,此错误还出现在生成器表达式中。
中继中的等效组件似乎是IPython.frontend.terminal.InteractiveShellEmbed。 但这在其他方面已被打破,而且显然没有经过太多测试。 有谁知道它的未来?
这可能与#136问题相同吗?
现在已修复:
amirbar[ipython]> python
Python 2.7.2+ (default, Oct 4 2011, 20:06:09)
[GCC 4.6.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from IPython import embed
>>> embed()
Python 2.7.2+ (default, Oct 4 2011, 20:06:09)
Type "copyright", "credits" or "license" for more information.
IPython 0.12.dev -- An enhanced Interactive Python.
? -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help -> Python's own help system.
object? -> Details about 'object', use 'object??' for extra details.
In [1]: a = 1
In [2]: def f(x):
...: return a*x
...:
In [3]: f(3)
Out[3]: 3
In [4]: b = 1
In [5]: (lambda : b)()
Out[5]: 1
In [6]:
有人可以解释一下解决此问题的方法吗? 我仍然遇到问题,但是仅当我通过方法调用删除了一层,并且仅当我从脚本运行而不是交互式地运行时。
OSX 10.6.8上的python 2.7.2,ipython 0.11和0.12都表现出相似的行为(对此注释使用0.12)
这是我们项目的一个问题,该项目(主要)具有嵌入式IPython shell。
testembed.py
from IPython import embed
def hi():
embed()
if __name__ == '__main__':
#embed()
hi()
在命令行上使用python testembed.py
运行此命令,并查看此会话:
Python 2.7.2 (default, Aug 29 2011, 12:33:18)
Type "copyright", "credits" or "license" for more information.
IPython 0.12 -- An enhanced Interactive Python.
? -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help -> Python's own help system.
object? -> Details about 'object', use 'object??' for extra details.
In [1]: import time
In [2]: def tim():
...: print time.time()
...:
In [3]: tim()
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
[snip] in <module>()
----> 1 tim()
[snip] in tim()
1 def tim():
----> 2 print time.time()
3
NameError: global name 'time' is not defined
In [4]:
但是,请注释掉对hi()
的调用并将其替换为embed()
调用:
Python 2.7.2 (default, Aug 29 2011, 12:33:18)
Type "copyright", "credits" or "license" for more information.
IPython 0.12 -- An enhanced Interactive Python.
? -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help -> Python's own help system.
object? -> Details about 'object', use 'object??' for extra details.
In [1]: import time
In [2]: def tim():
print time.time()
...:
In [3]: tim()
1328639444.29
In [4]:
在四处寻找之后,我认为这与此处使用的stack_depth
参数和以下代码块有关: https :
有什么想法吗?
这有些复杂,但是我认为这是Python本身的限制。
在失败的情况下,您实际上并没有将time
放入全局名称空间:因为您在hi
函数中调用了embed
,所以您以交互方式创建的新变量是本地的功能。 理想情况下, tim()
应该作为闭包工作,关闭对时间模块的引用。 但是,闭包仅在一次性编译包含函数时才起作用。 据我所知,没有办法动态定义闭包。 这个简单的例子失败了:
def outer():
import time
exec("def inner(): return time.time()")
return inner
outer()()
这可能是因为嵌套作用域相对较晚地添加到了Python中(它们是将来在2.1中导入的,并且始终在2.2中启用)。
好吧,我想我明白了。 看起来我们真的不能做任何事情,除了将我交互式编写的内容转储到文件中然后再读回该文件。对于我们希望能够交互式执行的操作而言,可能太复杂了。
谢谢,顺便说一句。
很抱歉继续在这里讲话,但这只会使交互式会话感觉很笨拙:
常规python:
>>> d={'one':1, 'two':2}
>>> getkeys=lambda: d.keys()
>>> getkeys()
['two', 'one']
常规IPython:
In [1]: d={'one':1, 'two':2}
In [2]: getkeys=lambda: d.keys()
In [3]: getkeys()
Out[3]: ['two', 'one']
嵌入式IPython:
>>> from IPython import embed
>>> embed()
Python 2.7.2 (default, Aug 29 2011, 12:33:18)
Type "copyright", "credits" or "license" for more information.
IPython 0.12.dev -- An enhanced Interactive Python.
? -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help -> Python's own help system.
object? -> Details about 'object', use 'object??' for extra details.
In [1]: d={'one':1, 'two':2}
In [2]: getkeys=lambda: d.keys()
In [3]: getkeys()
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
/Users/asadeveloper/Documents/Dev/code/pyon/bin/python in <module>()
----> 1 getkeys()
/Users/asadeveloper/Documents/Dev/code/pyon/bin/python in <lambda>()
----> 1 getkeys=lambda: d.keys()
NameError: global name 'd' is not defined
我想没有什么可以做的,但是我不明白为什么我们可以在常规python / ipython中创建动态闭包,而不是嵌入式版本。
由于Python作用域的奇怪之处,在标准Python / IPython中,我们实际上并未创建闭包。 d
是全局变量,访问这些规则的规则与闭包不同。 每个函数都保留对定义它的全局命名空间的引用( getkeys.func_globals
),因此它可以访问在那里定义的任何变量。
相反,当您进行闭包时,Python会将引用附加到它已关闭的每个变量上,这由编译器确定-但仅当同时编译内部函数和外部函数时,该函数才起作用。 看起来像这样:
In [8]: def outer():
a = 1
def inner():
return a
return inner
...:
In [9]: f = outer()
In [10]: f
Out[10]: <function __main__.inner>
In [11]: f.func_closure
Out[11]: (<cell at 0x9f5e344: int object at 0x9a830b0>,)
这样做可能是为了节省内存-如果闭包中包含对定义它的本地作用域的引用,则在该闭包处于活动状态时,不能释放该作用域中的任何变量。
我在OSX 10.7.3上使用Python 2.7.2和IPython 0.12.1,仍然存在此问题。 当我运行./manage.py shell
的Django的一个调用IPython.embed()
时,会出现问题。 但是,在Python Shell或简单的脚本文件中手动调用embed()
不会有问题。
我们可以直接做很多事情,但是我们应该鼓励第三方不要将embed
用于非平凡用途。
@takluyver您的意思是在这种情况下直接使用ipython更好吗?
Django可能以不会引起此问题的方式启动IPython,但这不是我们当前易于实现的方式。 当IPython以单独的本地和全局名称空间开头时,就会发生此问题。 Django没有理由需要单独的本地和全局名称空间,但这就是在函数中调用embed()
的含义。
供参考,这是Django中的代码:
https://code.djangoproject.com/browser/django/trunk/django/core/management/commands/shell.py
@takluyver,这很有意义,谢谢! 我为此打开了一张Django票。
@takluyver ,现在我们已经合并了embed_kernel,因此所有主要部分都就位了,您是否想解决一下此问题以使更精细的使用变得更容易?
我将看看哪种接口最有意义。
我在这个问题上仍然遇到麻烦。 我曾尝试缩小导致问题的原因,我能确定的最好办法是,它仅在Ubuntu 12.04上发生。 我已经在其他服务器上尝试了所有最新发行版本,并且工作正常。 但是,每当我在ipython中定义一个函数或使用%cpaste从另一个文件中粘贴一个函数时,该函数的内部都无法访问全局范围。 就动态地编写函数而言,这使得基本上不可能做任何有用的事情。
从其他工具(例如Django的debugsqlshell命令)调用IPython 0.13时,我仍然遇到此问题。 令人沮丧的是,像定义函数这样的基本操作完全被破坏了。
我认为embed()是使用这些接口的错误接口。 embed()是
旨在更多地检查正在运行的程序的状态,因此它使用
单独的本地和全局名称空间。 为了解决这个问题,ipython
需要从单个界面开始。 对不起,我还没来得及
找出最好的方法是什么。
不仅是ubuntu。 debian wheezy也表明了这一点。
仅供参考,上面创建的Django票证@liokm是https://code.djangoproject.com/ticket/18204 ,现在指向https://code.djangoproject.com/ticket/17078 ,它似乎已在树干中修复。 它应该降落在1.5。
我在使用Ipython 0.13.2的Ubuntu上遇到相同的问题
在Django 1.6中修复的@bkvirendra
但是1.6甚至还不稳定!
但是1.6甚至还不稳定!
软件并不总是稳定的,并且在发行版之间仍然可能存在错误。 但是在IPython中没有什么应该修复的。 即使我们在这里做某事,修复也不会在IPython中发布之前稳定下来。
问题仍然存在于ipython == 4.2.0中。 有趣的是,在Windows下这没问题,但是无法识别ubuntu全局变量。
用例:
from ipywidgets import interact, FloatSlider, IntSlider,RadioButtons, Dropdown
@interact(sv1 = radio_1, Scenario = drop_1, sv2 = slider_2)
def update_map(sv1,sv2, Scenario):
问题仍然存在。 IPython 3.1.0,Debian Whezzy。
如果我没记错的话,此问题已修复了一段时间,并且似乎已重新引入(在MacOS上使用IPython 5.1.0进行了复制,网址为:https://git.io/vPDrJ)。
(编辑:我可能记错了此修复程序。有可能我只是将所需的所有内容扔到了启动文件中,而不是使用嵌入)
以防万一这可以帮助我一直在使用这段代码作为解决方法的任何人
def fix_embed_globals(N=0):
# Get the parent frame
import inspect
frame_level0 = inspect.currentframe()
frame_cur = frame_level0
N = 2 # I may have this value off by one. I rewrote this function to use only standard calls
strict = False
for _ix in range(N + 1):
frame_next = frame_cur.f_back
if frame_next is None:
if strict:
raise AssertionError('Frame level %r is root' % _ix)
else:
break
frame_cur = frame_next
parent_frame = frame_cur
# Add locals to parent globals
parent_frame.f_locals.update(parent_frame.f_globals)
parent_frame.f_globals['_didfixipyglobals'] = True
每当我得到名称错误时,我都只是调用该函数。 它将当前框架中的所有本地人放入全局词典中。 它很笨拙,但在大多数情况下都可以使用。
如https://github.com/inducer/pudb/issues/103所述,使用嵌入式外壳程序时的临时解决方法是: globals().update(locals())
(仅在定义局部全局变量之后)。
嗯,这个错误的里程碑可以更改为下一个版本吗?
做完了
这个会解决吗?
AFAIK,我几年前的评论是:
我相信我们受到Python本身工作方式的限制。 闭包和动态评估不能很好地配合使用,而IPython无法修复它。 人们已经找到了将局部变量移动到全局名称空间的解决方法,但是这些都是会引起其他问题的黑客,因为他们正在修改全局名称空间。 我不打算将这样的解决方法放入IPython。 我宁愿留下我们未做的事情的问题,也不愿尝试过分聪明。
许多人以为他们想要embed()
,实际上应该改用start_ipython()
来避免这种问题。
我不明白,这让我很生气。
抱歉,我感到沮丧的是,如果您将它们键入到一个空的.py文件中,那么这些东西将无法正常工作
但是重新阅读历史记录,似乎这是Django的manage.py shell
一个问题,尤其是在我使用ipython的情况下,有90%的时间这样做,但是很容易忘记这种情况
令人尴尬的是,我正在使用过时的Django(1.4)进行大量工作
根据之前的评论,较新版本的Django Shell使用ipython的方式有所不同,可能没有问题吗? 例如https://code.djangoproject.com/ticket/17078
对于误解表示歉意
是的,我认为它对于Django 1.6是固定的。 如果您确实无法升级,则可能需要手动应用此修复程序。 看起来像这样: https :
最有用的评论
如https://github.com/inducer/pudb/issues/103所述,使用嵌入式外壳程序时的临时解决方法是:
globals().update(locals())
(仅在定义局部全局变量之后)。