<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
相信大家都用過 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 模組非常類似,可以自己看一下。
到此這篇關於Python實現自定義Jupyter魔法命令的文章就介紹到這了,更多相關Python Jupyter魔法命令內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45