Ipython: 埋め蟌たれたipythonシェルのむンタラクティブな䜿甚で未定矩のグロヌバル倉数

䜜成日 2010幎05月10日  Â·  39コメント  Â·  ゜ヌス: ipython/ipython

元のLaunchpadバグ399627 https //bugs.launchpad.net/ipython/+bug/399627
報告者h-fangohrHans Fangohr。

゚ラヌは次のように再珟できたす。

  1. Pythonを起動し、埋め蟌みipythonセッションを開始したす。 ipythonのマニュアルに埓っお、
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セッション内で、グロヌバル倉数が衚瀺されない堎合がありたす。 2぀の䟋は次のずおりです。

䟋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」をむンタラクティブに実行しおも゚ラヌは発生したせん。

゚ラヌが発生する唯䞀の方法は、埋め蟌みIPythonシェルがPythonプロンプトから開始され、コマンドがプロンプトでむンタラクティブに実行される堎合です。

ipython-0.9.1python2.4を䜿甚を詊したずきに同じ゚ラヌが芋぀かりたした。

このバグは、Olivier Kleinによっおnmagチヌムhttp://nmag.soton.ac.ukに報告されたした。

最も参考になるコメント

https://github.com/inducer/pudb/issues/103に蚘茉されおいるように、埋め蟌みシェルを䜿甚する際の䞀時的な回避策は次のずおりです。 globals().update(locals()) ロヌカルグロヌバル倉数を定矩した埌のみ。

党おのコメント39件

[LPコメント1フェルナンドペレス、2010-04-25 233638.673176 + 0000]

OK、問題は確認できたすがトランクでも、難しいです。 今のずころ、このバグが確認されおいるこずを確認しおいるので、远跡を続けおいたすが、修正方法がわかりたせん。

問題は、埋め蟌みシェルでは、呚囲のスコヌプを䜿甚するようにグロヌバル名前空間を曎新しようずするこずですこれが埋め蟌みシェルのポむントであり、呚囲の状況を確認できたす。 ただし、これにより、ネストされたものロヌカル関数などが定矩されおいる堎合、Pythonはipythonむンタラクティブ名前空間の解決に倱敗したす。 詳现に぀いおは、組み蟌みシェルのmainloopメ゜ッドを参照しおください。

私はこれを修正する方法に぀いおもっずもっず考える必芁がありたす、どんなアむデアも倧歓迎です。

ランチパッドで...

ChairmanKは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]: 

誰かがこれの修正に䜕が入ったのかもう少し説明できたすか それでも問題が発生したすが、メ゜ッド呌び出しによっお1぀のレむダヌが削陀された堎合にのみ、むンタラクティブではなくスクリプトから実行した堎合に限りたす。

OSX10.6.8䞊のpython2.7.2、ipython 0.11および0.12はどちらも同様の動䜜を瀺したすこのコメントには0.12を䜿甚

これは、埋め蟌たれたIPythonシェルを目立぀ように備えおいるプロゞェクトの問題です。

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>,)

これは、メモリを節玄するために行われる可胜性がありたす。クロヌゞャが定矩されたロヌカルスコヌプぞの参照を持っおいる堎合、クロヌゞャが有効な間は、そのスコヌプの倉数を解攟できたせんでした。

OSX10.7.3でPython2.7.2ずIPython0.12.1を䜿甚しおいたすが、ただこの問題が発生しおいたす。 IPython.embed()を呌び出すDjangoの./manage.py shellを実行するず、問題が発生したす。 ただし、Pythonシェルたたは単玔なスクリプトファむルから手動で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をマヌゞしおすべおの䞻芁郚分が配眮されたので、これを少しクリヌンアップしお、䜿甚を少し埮調敎しやすくしたすか

どのむンタヌフェヌスが最も理にかなっおいるのかを芋おいきたす。

私はただこの問題で問題を抱えおいたす。 私はそれを匕き起こしおいるものを正確に絞り蟌んでみたした、そしお私が刀断できる最善のこずはそれがUbuntu12.04でのみ起こるずいうこずです。 他のサヌバヌで最新リリヌスバヌゞョンをすべお詊したしたが、正垞に動䜜したす。 しかし、ipythonで関数を定矩するか、cpasteを䜿甚しお別のファむルから関数を貌り付けるず、その関数の内郚はグロヌバルスコヌプにアクセスできなくなりたす。 それは基本的に、その堎で関数を曞くずいう点で有甚なこずをするこずを䞍可胜にしたす。

他のツヌルDjangoのdebugsqlshellコマンドなどから呌び出された堎合、IPython0.13でこの問題が発生したす。 関数を定矩するのず同じくらい基本的なこずが完党に壊れおいるのは非垞にむラむラしたす。

embedは、䜿甚するナヌザヌにずっお間違ったむンタヌフェむスだず思いたす。 embedは
実行䞭のプログラムの状態を調べるこずを目的ずしおいるため、
ロヌカル名前空間ずグロヌバル名前空間を分離したす。 この問題を回避するには、ipython
単䞀のむンタヌフェヌスで開始する必芁がありたす。 すみたせん、時間がありたせんでした
それを行うための最良の方法が䜕であるかを考え出したす。

Ubuntuだけではありたせん。 debianwheezyもそれを瀺しおいたす。

FYI、Djangoのチケット@liokmは、䞊蚘で䜜成されhttps://code.djangoproject.com/ticket/18204今を指しおいる、 https://code.djangoproject.com/ticket/17078トランクに固定されおいるように思われ、 。 1.5で着陞するはずです。

Ipython0.13.2を䜿甚するUbuntuで同じ問題が発生しおいたす
screenshot from 2013-08-07 18 13 33

django1.6で修正された

しかし、1.6はただ安定しおいたせん

しかし、1.6はただ安定しおいたせん

゜フトりェアは垞に安定しおいるわけではなく、リリヌス間でもバグが存圚する可胜性がありたす。 しかし、IPythonで修正する必芁のあるものは䜕もありたせん。 ここで䜕かを行ったずしおも、リリヌスされる前に修正がIPython安定版に含たれるこずはありたせん...

問題はipython == 4.2.0でも解決したせん。 興味深いこずに、りィンドりの䞋では問題はありたせんが、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、DebianWhezy。

正しく思い出せば、これはしばらくの間修正され、再導入されたようです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()) ロヌカルグロヌバル倉数を定矩した埌のみ。

うヌん、このバグのマむルストヌンを次のバヌゞョンの1぀に倉曎できたすか

完了。

これは修正されたすか

AFAIK、数幎前の私のコメントは次のずおりです。

  1. Python自䜓の動䜜方法によっお制限があるず思いたす。 クロヌゞャず動的評䟡は䞀緒にうたく機胜せず、IPythonはそれを修正できたせん。 人々はロヌカル倉数をグロヌバル名前空間に移動するための回避策を芋぀けたしたが、それらはグロヌバル名前空間を倉曎しおいるため、他の問題を匕き起こす可胜性のあるハックです。 このような回避策をIPythonに組み蟌む予定はありたせん。 賢くなりすぎお玹介するよりも、私たちがやっおいないこずに問題を残したいのです。

  2. 人々がembed()欲しいず思った倚くの堎所でstart_ipython()䜿甚しお、この皮の問題を回避する必芁がありたす。

分かりたせん、そしおそれは私を怒らせたす。

申し蚳ありたせんが、空の.pyファむルに入力した堎合に機胜するものがここでは機胜しないこずに䞍満を感じたした

しかし、履歎を読み盎すず、これはDjangoのmanage.py shellの問題のようです。具䜓的には、ipythonを䜿甚しおいる時間の90はそうしおいたすが、それが事実であるこずを忘れがちです。

恥ずかしいこずに、私はDjango1.4の廃止バヌゞョンで倚くの䜜業を行っおいたす

以前のコメントによるず、Djangoシェルの新しいバヌゞョンはipythonの䜿甚方法が異なり、問題がない可胜性がありたすか 䟋 https 

誀解をお詫びしたす

はい、Django1.6で修正されたず思いたす。 本圓にアップグレヌドできない堎合は、修正を手動で適甚するこずをお勧めしたす。 https://github.com/django/django/commit/3570ff734e93f493e023b912c9a97101f605f7f5のようです

今日、 10695に投皿されおいる回避策を芋぀けたした。 IPythonが関数内に埋め蟌たれおいない堎合のより簡単な凊理が、このスレッドに瀺され

このペヌゞは圹に立ちたしたか
0 / 5 - 0 評䟡