2012-03-26 10 views
4

EDIT Ich isoliert ein echtes minimales Beispiel, das nicht funktioniert (es ist ein Teil von komplexeren Code); der Täter ist der inputhook Teil schließlich:wie ipython 0.12 einzubetten, so dass es Namespace des Aufrufers erbt?

def foo(): 
    exec 'a=123' in globals() 
    from IPython.frontend.terminal.embed import InteractiveShellEmbed 
    ipshell=InteractiveShellEmbed() 
    ipshell() 

# without inputhook, 'a' is found just fine 
import IPython.lib.inputhook 
IPython.lib.inputhook.enable_gui(gui='qt4') 

foo() 

Laufen mit 0,12:

In [1]: a 
--------------------------------------------------------------------------- 
NameError         Traceback (most recent call last) 
/tmp/<ipython-input-1-60b725f10c9c> in <module>() 
----> 1 a 

NameError: name 'a' is not defined 

Was die Art und Weise um sein würde?

+0

Es scheint in der Entwicklungsversion zu arbeiten - vielleicht gibt es einen Bug mit 0,12 war, die behoben worden ist:

durch die Schaffung der InteractiveShellEmbed Instanz erste ganz gut, arbeitet Diese Version soll. –

+0

@TomasK: Ich musste das Beispiel komplizieren, damit es wirklich nicht funktioniert. Es hängt mit dem qt4-Inputhook zusammen; es funktionierte gut mit 0.11. – eudoxos

Antwort

2

Das Problem liegt an this call zu InteractiveShell.instance() in der Qt-Integration, wenn vor IPython initialisiert aufgerufen wird. Wenn dies aufgerufen wird, bevor Ihre eingebettete Shell erstellt wird, werden einige Annahmen nicht erfüllt. Die Lösung besteht darin, Ihr eingebettetes Shell-Objekt zuerst zu erstellen, dann sollten Sie kein Problem haben. Und Sie können das gleiche Objekt von irgendwo anders in Ihrem Code abrufen, indem Sie einfach InteractiveShellEmbed.instance() aufrufen.

from IPython.frontend.terminal.embed import InteractiveShellEmbed 
# create ipshell *before* calling enable_gui 
# it is important that you use instance(), instead of the class 
# constructor, so that it creates the global InteractiveShell singleton 
ipshell = InteractiveShellEmbed.instance() 

import IPython.lib.inputhook 
IPython.lib.inputhook.enable_gui(gui='tk') 

def foo(): 
    # without inputhook, 'a' is found just fine 
    exec 'a=123' in globals() 
    # all calls to instance() will always return the same object 
    ipshell = InteractiveShellEmbed.instance() 
    ipshell() 

foo() 
+0

Sehr schön. Ich habe jedoch ein weiteres Problem entdeckt. Ich importiere ein größeres Paket mit 'from yade import *'; Wenn Sie dies tun (vor oder nach dem Erstellen der Shell-Instanz), tritt erneut ein Fehler auf ("a" ist nicht definiert). Es ruft intern 'PyEval_InitThreads' und viele andere Dinge auf. Was könnte eine mögliche Störung dort sein? – eudoxos

+0

OK, das Problem schien in Zusammenhang mit zirkulären Importen oder etwas Ähnlichem zu stehen; funktioniert jetzt gut. – eudoxos

+0

@minrk Könnten wir auch die Option '' user_ns'' beim Initiieren der IPython-Shell verwenden? – hosolmaz