Python实现自定义Jupyter魔法命令
作者:古明地觉 发布时间:2022-03-10 11:47:04
相信大家都用过 jupyter,也用过里面的魔法命令,这些魔法命令都以 % 或者 %% 开头,我们举个例子。
用法还是比较简单的,但是我们能不能自定义魔法命令呢?毫无疑问是可以的,因为上面的 %%cython 就是 Cython 模块自定义的。
所以命令可以是 jupyter 内置的,比如 %time,直接拿来就能用;还可以是第三方模块里面的,在 jupyter 通过 %load_ext 加载之后,再嵌入进来。下面就来看看如何自定义魔法命令。
from IPython.core.magic import (
magics_class,
Magics,
line_magic,
cell_magic
)
@magics_class
class MagicOrder(Magics):
"""
自定义一个类,类名叫什么无所谓
但要继承 Magics,并且要被 magics_class 装饰
"""
@line_magic
def hello(self, line):
"""
在 jupyter 中就可以使用如下命令,比如:
%hello <Your Code>,然后就会调用这个 hello 方法
参数 line 就是 %hello 后面的代码
"""
print(f"line: {line}")
@cell_magic
def world(self, line, cell):
"""
在 jupyter 中就可以使用如下命令,比如:
%%world
<Your Code>
<Your Code>
...
然后就会调用这个 world 方法
参数 cell 就是 %%world 下面整个单元格的代码
然后还有一个参数 line,它表示 %%world 所在行后面的代码
但对于 %% 开头的命令来说,我们一般都会新起一行,然后写代码
所以 line 这个参数暂时用不到
"""
print(f"line: \n{line}")
print("-----------------")
print(f"cell: \n{cell}")
# 必须定义 load_ipython_extension 函数
# %load_ext 本质上也是加载一个模块
# 但它会自动调用该函数
def load_ipython_extension(ip):
# 在函数内部,我们将类 MagicOrder 注册进去
# 然后就可以使用它内部的魔法命令了
ip.register_magics(MagicOrder)
# 如果不定义此函数,那么使用 %load_ext 加载时会报错
# The xxx module is not an IPython extension.
当前模块叫 main.py,我们来测试一下:
结果没有问题,但说实话对于 %% 开头的命令来说,我们很少会在它后面写代码,基本都是新起一行,就像下面这个样子。
自定义命令我们已经实现了,并且也知道怎么获取输入的代码了,下面要做的就是执行它。而将字符串当成代码执行,我们可以使用内置函数 exec。
@magics_class
class MagicOrder(Magics):
@line_magic
def hello(self, line):
exec(line)
@cell_magic
def world(self, line, cell):
exec(cell)
代码的其它部分不变,然后你觉得接下来调用魔法命令会执行成功吗?我们测试一下:
神奇的地方出现了,虽然命令执行成功了,但执行完之后,告诉我们变量未定义。其实原因很好想,我们调用 exec 的时候没有指定名字空间,那么默认会影响 exec 函数所在的名字空间,即 hello 和 world 函数的名字空间。
当打开一个 jupyter 的时候,内部相当于启动了一个 shell,所以在调用 exec 的时候,应该将整个 shell 的名字空间传进去。
from IPython.core.magic import (
magics_class,
Magics,
line_magic,
cell_magic,
needs_local_scope
)
@magics_class
class MagicOrder(Magics):
@line_magic
def hello(self, line):
# 通过 self.shell.user_ns
# 可以拿到当前 shell 的名字空间
# 注意:包含所有的单元格
local_ns = self.shell.user_ns
# 在 local_ns 当中执行代码
exec(line, local_ns, local_ns)
@needs_local_scope
@cell_magic
def world(self, line, cell, local_ns):
# 或者通过 needs_local_scope 装饰器
# 这样在调用函数的时候,会额外传递一个 local_ns 参数
# 该参数和 self.shell.user_ns 等价
exec(cell, local_ns, local_ns)
def load_ipython_extension(ip):
ip.register_magics(MagicOrder)
然后再来测试一下:
此时就没有任何问题了。
下面我们模仿 jupyter 的 %time 命令,实现一个 %my_time,来加深一遍印象。
@magics_class
class MagicOrder(Magics):
@needs_local_scope
@line_magic
def my_time(self, line, local_ns):
start = time.perf_counter()
exec(line, local_ns, local_ns)
end = time.perf_counter()
print(f"总耗时: {round(end - start, 3)}")
测试一下:
结果没有问题,是我们想要的结果。
最后再来看看如何设置可选参数,举一个 Cython 的例子:
我们说对于以 %% 开头的命令,应该新起一行,在它的下面写代码。而之所以新起一行,是因为命令所在的行,要用于设置可选参数。那么问题来了,如何设置指定的可选参数呢?
from IPython.core.magic import (
magics_class,
Magics,
cell_magic,
needs_local_scope
)
from IPython.core import magic_arguments
@magics_class
class MagicOrder(Magics):
@magic_arguments.magic_arguments()
# 在 jupyter 中可以通过 -n=xxx 或者 --name=xxx
# 然后是 dest="name",用于指定参数的名字
# 后续便可以通过 name 字段来获取该参数的值
@magic_arguments.argument(
"-n", "--name", dest="name", default="satori"
)
# "-" 和 "--" 可以只出现一个,并且默认解析得到的是字符串
# 而 age 我们希望是整数,所以指定 type 为 int
# 解析完参数之后,会自动调用 int 进行转化
# 如果不指定该参数,则使用 default
# 而这里没有 default,那么结果就是 None
@magic_arguments.argument(
"--age", dest="age", type=int
)
@magic_arguments.argument(
"-h", "--hobby", dest="hobby", default=[],
action="append"
)
@needs_local_scope
@cell_magic
def order(self, line, cell, local_ns):
# 显然 line 就是可选参数,cell 就是代码块
exec(cell, local_ns, local_ns)
# 解析参数
args = magic_arguments.parse_argstring(
self.order, line)
# 打印
print(args)
def load_ipython_extension(ip):
ip.register_magics(MagicOrder)
我们测试一下:
还是很简单的,而且这里的参数解析和 argparse 模块非常类似,可以自己看一下。
来源:https://mp.weixin.qq.com/s/yiBWcoZitavGWBA0osedow
猜你喜欢
- win7 pycharm设置界面全黑色方法:1.设置默认PyCharm解析器: 操作如下:Python–>Preferences–&g
- 本文实例讲述了Python实现简单的列表冒泡排序和反转列表操作。分享给大家供大家参考,具体如下:# -*- coding:utf-8 -*-
- 10月15日,Adobe公司正式面向全球公布了第10个版本的Flash播放器,这一版本播放器的昵称是大家已经所熟知的“宇宙”。这是一款增加了
- 主要作用与拷贝文件用的。1.shutil.copyfileobj(文件1,文件2):将文件1的数据覆盖copy给文件2。import shu
- 这篇博客将介绍如何使用OpenCV和深度学习应用全面嵌套的边缘检测。并将对图像和视频流应用全面嵌套边缘检测,然后将结果与OpenCV的标准C
- 负责Web编写的前端人员,都清楚可以通过W3验证服务功能,来在线验证自己编写的XHTML代码是否正确,在验证期间,最容易出现的错误往往都是在
- 这个主要应用于,获取用户输入的时候,防止用户不小心,多输入了一个空格,导致验证无法通过,多用于用户名跟密码的,好多情况下,大家复制的winr
- 问题1:使用.net2005自带的SQL-Express连接不上。解决方法:1.网络防火墙阻止数据库连接;2.默认SQL-Express没有
- 本文实例讲述了js实现的全国省市二级联动下拉选择菜单。分享给大家供大家参考。具体如下:运行效果截图如下:具体代码如下:<!DOCTYP
- 如下所示: out = subprocess.getstatusoutput('adb shell pm
- 精妙的"SQL"语句:◆复制表(只复制结构,源表名:a 新表名:b)SQL: select * into b from
- 一个简易的TCP端口扫描器,使用python3实现。需求:扫描目标网站开放哪些端口号,将所有开放的端口号输出。分析:使用socket连接,如
- 我们可以用动态产生变量的方法,从表格里捕捉数据,动态地创造“剥离”变量引号并且“清理”它,见下列代码,我们只需键入变量名称,选择 query
- 网上看到的python去掉字符串中的标点符号的方法,大多是基于python2的,不适用python3,调整后代码如下:代码lower_cas
- try 块允许您测试代码块以查找错误。except 块允许您处理错误。finally 块允许您执行代码,无论 try 和 except 块的
- 目录前言1-下载python3.8压缩包2-解压缩安装包3-安装依赖工具4-安装python3.85-修改python2软链接6-修改yum
- Function ChkInvaildWord(Words) Const InvaildWords=&quo
- 一、Ajax简介Ajax被认为是(Asynchronous JavaScript and XML)的缩写,允许浏览器与服务器通信而无需刷新当
- 本文实例讲述了python中as用法。分享给大家供大家参考。具体分析如下:import some # some 为一个模组如果想要改变被导入
- 1.增加维度下面给出两个样例样例1:[1, 2, 3] ==> [[1],[2],[3]]import tensorflow as t