如何将HTML嵌入IPython输出中?

252 投票
6 回答
348015 浏览
提问于 2025-04-20 03:37

有没有办法把渲染好的HTML内容嵌入到IPython的输出中呢?

一种方法是使用

from IPython.core.display import HTML
HTML('<a href="http://example.com">link</a>')

或者(IPython多行单元的别名)

%%html
<a href="http://example.com">link</a>

这样可以返回一个格式化的链接,但有几点需要注意:

  1. 这个链接不能直接在控制台中打开浏览器显示网页。不过,IPython笔记本是支持真实渲染的。
  2. 我不知道如何在比如说一个列表或者打印的表格中渲染HTML()对象。你可以使用df.to_html(),但这样做不能在单元格里创建链接。
  3. 在PyCharm的Python控制台中,这个输出是不可交互的(因为它不是QT)。

我该如何克服这些问题,让IPython的输出更具互动性呢?

6 个回答

4

首先,代码如下:

from random import choices

def random_name(length=6):
    return "".join(choices("abcdefghijklmnopqrstuvwxyz", k=length))
# ---

from IPython.display import IFrame, display, HTML
import tempfile
from os import unlink

def display_html_to_frame(html, width=600, height=600):
    name = f"temp_{random_name()}.html"
    with open(name, "w") as f:
        print(html, file=f)
    display(IFrame(name, width, height), metadata=dict(isolated=True))
    # unlink(name)
    
def display_html_inline(html):
    display(HTML(html, metadata=dict(isolated=True)))

h="<html><b>Hello</b></html>"    
display_html_to_iframe(h)
display_html_inline(h)

一些快速说明:

  • 对于简单的内容,通常可以直接使用内联HTML。如果你在使用一个框架,比如一个大型的JavaScript可视化框架,可能需要使用IFrame。因为在浏览器中运行Jupyter本身就已经够复杂了,再加上随机的HTML嵌入就更麻烦了。
  • 那个奇怪的参数metadata=dict(isolated=True)并不会像旧文档所说的那样将结果隔离在IFrame中。它似乎是为了防止clear-fix重置所有内容。这个标志现在没有文档说明了:我发现使用它可以让某些display: grid样式正确显示。
  • 这个IFrame解决方案会写入一个临时文件。你可以使用数据URI,像这里描述的那样,但这会让调试输出变得困难。Jupyter的IFrame函数不接受datasrcdoc属性。
  • tempfile模块创建的文件不能被其他进程共享,所以才有random_name()这个函数。
  • 如果你在IFrame中使用HTML类,会收到一个警告。这可能每个会话只出现一次。
  • 你可以在单元格的顶层使用HTML('Hello, <b>world</b>'),它的返回值会被渲染。在函数内部,使用display(HTML(...)),就像上面那样。这也允许你自由混合使用displayprint调用。
  • 奇怪的是,IFrames的缩进比内联HTML稍微多一些。
9

根据@Harmon的补充,看来你可以把 displayprint 这两个语句结合起来使用……如果你需要的话。或者,也许把整个HTML格式化成一个字符串,然后再用display会更简单。不管怎样,这都是个不错的功能。

display(HTML('<h1>Hello, world!</h1>'))
print("Here's a link:")
display(HTML("<a href='http://www.google.com' target='_blank'>www.google.com</a>"))
print("some more printed text ...")
display(HTML('<p>Paragraph text here ...</p>'))

输出的内容大概是这样的:


你好,世界!

这是一个链接:

www.google.com

还有一些打印的文本……

这里是段落文本……


25

相关内容:在构建一个类的时候,可以使用 def _repr_html_(self): ... 来创建这个类实例的自定义HTML表示:

class Foo:
    def _repr_html_(self):
        return "Hello <b>World</b>!"

o = Foo()
o

会显示为:

你好 世界!

想了解更多信息,可以参考 IPython的文档

一个高级示例:

from html import escape # Python 3 only :-)

class Todo:
    def __init__(self):
        self.items = []

    def add(self, text, completed):
        self.items.append({'text': text, 'completed': completed})

    def _repr_html_(self):
        return "<ol>{}</ol>".format("".join("<li>{} {}</li>".format(
            "☑" if item['completed'] else "☐",
            escape(item['text'])
        ) for item in self.items))

my_todo = Todo()
my_todo.add("Buy milk", False)
my_todo.add("Do homework", False)
my_todo.add("Play video games", True)

my_todo

将显示为:

  1. ☐ 买牛奶
  2. ☐ 做作业
  3. ☑ 玩视频游戏
60

之前,Jupyter Notebooks 开始不允许在 HTML 内容中使用 JavaScript [#3118]。这里有两个解决办法:

使用本地 HTML

如果你想在你的页面中嵌入一个带有 JavaScript 的 HTML 页面,最简单的方法就是把你的 HTML 文件保存在和你的笔记本同一个文件夹里,然后按照下面的方式加载这个 HTML:

from IPython.display import IFrame

IFrame(src='./nice.html', width=700, height=600)

使用远程 HTML

如果你更喜欢在线的解决方案,可以把你的 HTML 页面上传到亚马逊的 S3 "桶"里,然后更改这个桶的设置,让它可以托管一个静态网站,接着在你的笔记本中使用一个 Iframe 组件:

from IPython.display import IFrame

IFrame(src='https://s3.amazonaws.com/duhaime/blog/visualizations/isolation-forests.html', width=700, height=600)

这样就可以在一个 iframe 中显示你的 HTML 内容和 JavaScript,就像在其他网页上一样:

<iframe src='https://s3.amazonaws.com/duhaime/blog/visualizations/isolation-forests.html', width=700, height=600></iframe>

371

这对我来说似乎有效:

from IPython.core.display import display, HTML
display(HTML('<h1>Hello, world!</h1>'))

诀窍是也要把它包裹在 display 里面。

来源:http://python.6.x6.nabble.com/Printing-HTML-within-IPython-Notebook-IPython-specific-prettyprint-tp5016624p5016631.html

编辑:

from IPython.display import display, HTML

为了避免:

DeprecationWarning: Importing display from IPython.core.display is 
deprecated since IPython 7.14, please import from IPython display

撰写回答