#15383·ipython

自定义懒加载魔法在导入之前不会显示帮助(?)

作者: krassowski创建于 2026年9月2日更新于 2026年9月9日

Before 9.17.0, it did not work at all. Since 9.17.0, it sometimes works on the second attempt (depending on the order of registration):

python
import sys, types
from IPython.core.interactiveshell import InteractiveShell
from IPython.core.magic import Magics, cell_magic, line_magic, magics_class


@magics_class
class LineHalf(Magics):
    @line_magic
    def dual(self, line):
        """The line half of %dual."""


@magics_class
class CellHalf(Magics):
    @cell_magic
    def dual(self, line, cell):
        """The cell half of %%dual."""


sys.modules["provider"] = provider = types.ModuleType("provider")
provider.LineHalf, provider.CellHalf = LineHalf, CellHalf

ip = InteractiveShell()
ip.magics_manager.register_lazy("dual", "provider:LineHalf", "line")
ip.magics_manager.register_lazy("dual", "provider:CellHalf", "cell")

ip.run_cell("%%dual?")  # does not work "Object `%%dual` not found."
ip.run_cell("%%dual?")  # works, shows "Docstring: The cell half of %%dual."

If we swap the registration order, neither works:

python
import sys, types
from IPython.core.interactiveshell import InteractiveShell
from IPython.core.magic import Magics, cell_magic, line_magic, magics_class


@magics_class
class LineHalf(Magics):
    @line_magic
    def dual(self, line):
        """The line half of %dual."""


@magics_class
class CellHalf(Magics):
    @cell_magic
    def dual(self, line, cell):
        """The cell half of %%dual."""


sys.modules["provider"] = provider = types.ModuleType("provider")
provider.LineHalf, provider.CellHalf = LineHalf, CellHalf

ip = InteractiveShell()
ip.magics_manager.register_lazy("dual", "provider:CellHalf", "cell")
ip.magics_manager.register_lazy("dual", "provider:LineHalf", "line")

ip.run_cell("%%dual?")  # does not work "Object `%%dual` not found."
ip.run_cell("%%dual?")  # does not work "Object `%%dual` not found."

Also, there are issues when overwriting the built-in dual magic with only a line magic:

python
import sys, types
from IPython.core.interactiveshell import InteractiveShell
from IPython.core.magic import Magics, line_magic, magics_class


@magics_class
class MyMagics(Magics):
    @line_magic
    def time(self, line):
        """My own %time."""


sys.modules["provider"] = provider = types.ModuleType("provider")
provider.MyMagics = MyMagics

ip = InteractiveShell()
ip.magics_manager.register_lazy("time", "provider:MyMagics")

ip.run_cell("time?")  # my own %time
ip.run_cell("%%time?")  # expected: IPython's %%time docs
ip.run_cell("%%time\npass")  # expected: a wall time report

内容来源: ipython/ipython