如何在从ipzope调用时将类路径传递给ipython笔记本?
我一直在使用从ipzope(buildout)设置的iypthon,使用起来没有问题。
现在我想用ipython的笔记本功能,但设置得不太好。
每当我创建一个新的笔记本时,IPython的内核就会因为一个ImportError
而停止运行(见下文)。我猜在IPython.html.notebook.start()
中创建的线程打开了webbrowser
,但没有把调用进程的sys.path
传递过去。
我的解决办法是把ipzope
中的路径添加到PYTHONPATH
。
当我添加了所有路径后,ipython的笔记本就能正常工作,我可以调试和操作Plone。
如果我只把ipython
、pyzmq
、Jinja
和tornado
添加到PYTHONPATH
,ipython的笔记本虽然能工作,但无法访问ipzope
中的变量(比如app
、utils
等)。
问题:有没有什么方法可以在不使用PYTHONPATH
的情况下将路径传递给ipython的笔记本?
我从ipzope
启动ipython的笔记本,使用的是
sys.argv[1:1] = "notebook --ip=192.168.45.135 --profile=zope".split()
这个ImportError是:
IPython Notebook 14-03-22 14:57:17.141 [NotebookApp] Connecting to: tcp://127.0.0.1:50948
2014-03-22 14:57:17.143 [NotebookApp] Kernel started: b573fbc0-5dee-410b-91cb-01afd2e9acce
Traceback (most recent call last):
File "<string>", line 1, in <module>
ImportError: No module named IPython.kernel.zmq.kernelapp
1 个回答
我引用了 Min RK
,他是一个 IPython的开发者:
“当你启动普通的终端IPython时,shell是在同一个进程中创建的。这意味着IPython在你对sys.path所做的更改的同一个上下文中执行,所以这些更改会产生预期的效果。在笔记本中,只有笔记本服务器存在于那个上下文中。内核是作为子进程启动的,因此在启动时会重新创建sys.path,遵循Python进程的标准程序,并不会继承父进程中可能发生的对sys.path的任何运行时更改。” (https://github.com/ipython/ipython/issues/5420)
我的解决方案
因此,将路径传递给笔记本的唯一方法是通过 PYTHONPATH
。
目前我的解决方法是在脚本中设置 os.environ['PYTHONPATH'] = ':'.join(sys.path)
。这样你就不需要去修改系统的PYTHONPATH(如果有的话),并且可以确保所有必要的路径都会传递给内核。
os.environ
作为 Popen
的 env
参数传递给 launch_kernel
中的子进程(.../ipython-1.2.1-py2.7.egg/IPython/kernel/launcher.py
)。
如果你需要使用ipython的笔记本,并且想让buildout生成脚本,可以在你的buildout中添加以下内容(例如在 .../Plone-4.3.2/zeocluster/develop.cfg
中)
parts +=
...
ipzopenb
...
[ipzopenb]
recipe = zc.recipe.egg
eggs =
ipython
pyzmq
tornado
Jinja2
#following for nbconvert
Pygments
Sphinx
${client2:eggs}
initialization =
import sys, os
os.environ["INSTANCE_HOME"] = "${client2:location}"
os.environ['PYTHONPATH'] = ':'.join(sys.path)
sys.argv[1:1] = "notebook --ip=192.168.45.135 --profile=zope".split()
scripts = ipython=ipzopenb
...
[versions]
Jinja2 = 2.7.2
Pygments = 1.6
Sphinx = 1.2.2