制作简单的 Python 包装器内核¶
你可以复用 IPython 的内核机制来轻松制作新的内核。这对有 Python 绑定的语言很有用,比如 Hy (见 Calysto Hy),或者可以在 tty 中使用 pexpect 控制 REPL 的语言,如 bash。
参见
- bash_kernel
一个简单的 bash 的内核,用这个机制写的
Metakernel 库使编写一个封装的内核更容易,其中包括一套基本的行和单元格魔法。它还有一个 ProcessKernel
子类,使得编写使用 pexpect
的内核变得容易。请看 Octave 内核 作为一个例子。
所需步骤¶
子类化 ipykernel.kernelbase.Kernel
,并实现以下方法和属性:
- class MyKernel¶
- implementation¶
- implementation_version¶
- banner¶
Kernel info 回复的信息。’Implementation’ 指的是内核(如 IPython),而不是语言(如 Python)。’banner’ 是在控制台 UI 中在第一个提示前显示给用户的。所有这些值都是字符串。
- language_info¶
Kernel info 回复的语言信息,在一个字典中。这应该包含键
mimetype
和目标语言的代码 mimetype(例如:'text/x-python'
),正在实现的语言的name
(例如:'python'
)和file_extension
(例如:'.py'
)。如果需要与language
不同,它也可以包含键codemirror_mode
和pygments_lexer
。以后还可以在此基础上增加其他键。
- do_execute(code, silent, store_history=True, user_expressions=None, allow_stdin=False)¶
执行用户代码。
- 参数
code (str) – 要执行的代码。
silent (bool) – 是否显示输出。
store_history (bool) – 是否在历史中记录这段代码并增加执行次数。如果 silent 为 True,则隐含为 False。
user_expressions (dict) – 名称与表达式的映射,以便在代码运行后进行评估。如果你需要,你可以忽略这一点。
allow_stdin (bool) – 前端是否可以按要求提供输入(例如对于 Python 的
raw_input()
)。
你的方法应该返回一个包含 Execution results 中描述的字段的 dict。为了显示输出,它可以使用
send_response()
来发送消息。如果在执行过程中发生了错误,除了send_response()
之外,还应该通过 Execution results 发送一个 error 类型的消息,其 status 为 error。参见 Jupyter 中的消息传递 了解不同消息类型的细节。
为了启动你的内核,在你的模块末尾添加以下内容
if __name__ == '__main__':
from ipykernel.kernelapp import IPKernelApp
IPKernelApp.launch_instance(kernel_class=MyKernel)
现在创建一个 JSON 内核规格文件,并使用 jupyter kernelspec install </path/to/kernel>
安装它。将你的内核模块放置在 Python 可以导入的任何地方(测试时试试当前目录)。最后,你可以使用 jupyter console --kernel <mykernelname>
来运行你的内核。注意,在下面的例子中 <mykernelname>
是 echo
。
例子¶
参见
- echo_kernel
下面是一个打包的、可安装的浓缩例子的版本。
echokernel.py
会简单地将任何输入的信息回传到 stdout
from ipykernel.kernelbase import Kernel
class EchoKernel(Kernel):
implementation = 'Echo'
implementation_version = '1.0'
language = 'no-op'
language_version = '0.1'
language_info = {
'name': 'Any text',
'mimetype': 'text/plain',
'file_extension': '.txt',
}
banner = "Echo kernel - as useful as a parrot"
def do_execute(self, code, silent, store_history=True, user_expressions=None,
allow_stdin=False):
if not silent:
stream_content = {'name': 'stdout', 'text': code}
self.send_response(self.iopub_socket, 'stream', stream_content)
return {'status': 'ok',
# The base class increments the execution count
'execution_count': self.execution_count,
'payload': [],
'user_expressions': {},
}
if __name__ == '__main__':
from ipykernel.kernelapp import IPKernelApp
IPKernelApp.launch_instance(kernel_class=EchoKernel)
这是内核规格 kernel.json
文件,用于此
{"argv":["python","-m","echokernel", "-f", "{connection_file}"],
"display_name":"Echo"
}
可选步骤¶
你可以覆盖一些其他的方法来改善你的内核的功能。所有这些方法都应该返回一个字典,如 messaging spec 的相关部分所描述的。
- class MyKernel¶
- do_complete(code, cursor_pos)¶
代码自动补全
- 参数
code (str) – 已经存在的代码
cursor_pos (int) – 要求补全的代码中的位置
参见
Completion 消息
- do_inspect(code, cursor_pos, detail_level=0)¶
对象自省
- 参数
code (str) – 代码
cursor_pos (int) – 代码中要求自省的位置
detail_level (int) – 0 或 1 代表更多或更少的细节。在 IPython 中,1 得到的是源代码。
参见
- do_history(hist_access_type, output, raw, session=None, start=None, stop=None, n=None, pattern=None, unique=False)¶
历史访问。只有相关的历史请求类型的相关参数才会被传递,所以你的方法定义必须有这里显示的所有参数的默认值。
参见
History 消息
- do_is_complete(code)¶
在类似于控制台的界面中输入的代码是否已经完成并准备执行,还是应该显示一个继续提示?
- 参数
code (str) – 到目前为止输入的代码 —— 可能有多行
参见
- do_shutdown(restart)¶
关闭内核。你只需要处理你自己的清理工作 ——— 内核机器会在停止前处理好自己的事情。
- 参数
restart (bool) – 事后是否会再次启动内核
参见