如何从IPython';什么是嵌入?
我有时在脚本中的某个位置使用如何从IPython';什么是嵌入?,python,import,closures,ipython,Python,Import,Closures,Ipython,我有时在脚本中的某个位置使用embed,以快速充实一些本地功能。最简单的例子: #!/usr/bin/env python # ... import IPython IPython.embed() 开发本地功能通常需要新的导入。但是,在函数中使用时,在IPython会话中导入模块似乎不起作用。例如: In [1]: import os In [2]: def local_func(): return os.path.sep In [3]: local_func() ----------
embed
,以快速充实一些本地功能。最简单的例子:
#!/usr/bin/env python
# ...
import IPython
IPython.embed()
开发本地功能通常需要新的导入。但是,在函数中使用时,在IPython会话中导入模块似乎不起作用。例如:
In [1]: import os
In [2]: def local_func(): return os.path.sep
In [3]: local_func()
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-3-f0e5d4635432> in <module>()
----> 1 local_func()
<ipython-input-2-c530ce486a2b> in local_func()
----> 1 def local_func(): return os.path.sep
NameError: global name 'os' is not defined
模块名称可能是“关闭”最常见的东西
这个问题有什么解决办法吗
更新:这个问题不仅适用于闭包,而且也适用于
免责声明:我会自己发布一个(不满意的)问题答案——不过还是希望有更好的解决方案。Update:同样只是一个解决办法,但稍微简单一些:
globals().Update(locals())
我没有一个通用的解决方案,但至少有一个解决方法:定义本地函数后,可以将会话的
locals()
添加到刚刚定义的函数的func\u globals
,例如:
In [1]: import os
In [2]: def local_func(): return os.path.sep
In [3]: local_func.func_globals.update(locals())
In [4]: local_func()
Out[4]: '/'
但是,应注意,这只是“手动关闭”,在以下情况下不会作为常规关闭:
In [1]: x = 1
In [2]: def local_func(): return x
In [3]: local_func.func_globals.update(locals())
In [4]: local_func()
Out[4]: 1
In [5]: x = 42
In [6]: local_func() # true closure would return 42
Out[6]: 1
In [7]: local_func.func_globals.update(locals()) # but need to update again
In [8]: local_func()
Out[8]: 42
至少它可以解决臭名昭著的
全局名称“…”没有定义的导入问题。我也有同样的问题。我使用这个技巧来处理在函数外部调用embed()
的情况,因此globals()
和locals()
应该是同一个字典
最简单的方法是在ipython启动后调用以下函数
ipy = get_ipython()
setattr(ipy.__class__, 'user_global_ns', property(lambda self: self.user_ns))
另一种方法是子类化InteractiveShellEmbed
class InteractiveShellEmbedEnhanced(InteractiveShellEmbed):
@property
def user_global_ns(self):
if getattr(self, 'embedded_outside_func', False):
return self.user_ns
else:
return self.user_module.__dict__
def init_frame(self, frame):
if frame.f_code.co_name == '<module>':
self.embedded_outside_func = True
else:
self.embedded_outside_func = False
(默认行为是由于
a
和time
未添加到globals()
和ipython
不会对局部函数(上面定义的lambda)进行闭包,并坚持在全局范围内查找变量。搜索closure
)截至2017年2月,我仍然注意到sys.version的问题是2.7.12(默认值,2016年11月19日06:48:10)[GCC 5.4.0 20160609]
。非常有趣。你认为把这些贡献给iPython有意义吗?也许这可以解决问题,@bluenote10我不是python或IPython方面的专家。我不确定在函数外部启动时,该代码是否在所有情况下都能工作。我只能分享我的代码,让专家告诉我它是作为解决方案还是指向解决问题的方向。我已经将一个更完整的代码片段放到了您的中,它还提供了从函数嵌入IPython时的帮助。
class InteractiveShellEmbedEnhanced(InteractiveShellEmbed):
@property
def user_global_ns(self):
if getattr(self, 'embedded_outside_func', False):
return self.user_ns
else:
return self.user_module.__dict__
def init_frame(self, frame):
if frame.f_code.co_name == '<module>':
self.embedded_outside_func = True
else:
self.embedded_outside_func = False
a=3
(lambda :a)() # default behavior: name 'a' is not defined
import time
(lambda: time.time())() # default behavior: name 'time' is not defined