是否可以将呈现的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>

返回一个格式化的链接,但是

这个链接不会从控制台打开带有网页本身的浏览器。不过,IPython笔记本支持真实渲染。 我不知道如何渲染HTML()对象内,说,一个列表或熊猫打印表。您可以执行df.to_html(),但不需要在单元格中创建链接。 这个输出在PyCharm Python控制台中不是交互式的(因为它不是QT)。

如何克服这些缺点并使IPython输出更具交互性呢?


当前回答

不久前,Jupyter笔记本开始从HTML内容中剥离JavaScript[#3118]。这里有两种解决方案:

提供本地HTML

如果你现在想在你的页面上嵌入一个带有JavaScript的HTML页面,最简单的方法是将你的HTML文件保存到笔记本电脑的目录中,然后按如下方式加载HTML:

from IPython.display import IFrame

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

提供远程HTML

如果你更喜欢托管解决方案,你可以将你的HTML页面上传到S3中的Amazon Web Services“bucket”中,更改桶上的设置,使桶托管一个静态网站,然后在你的笔记本中使用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>

其他回答

扩展上面的@Harmon,看起来你可以把显示和打印语句结合在一起…如果你需要的话。或者,将整个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

再来点印刷品……

段落文本在这里…


相关:当构造一个类,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

将呈现:

买牛奶 做功课 ☑玩电子游戏

要在循环中做到这一点,你可以这样做:

display(HTML("".join([f"<a href='{url}'>{url}</a></br>" for url in urls])))

这实际上是在循环中创建html文本,然后使用display(html())构造将整个字符串显示为html

不久前,Jupyter笔记本开始从HTML内容中剥离JavaScript[#3118]。这里有两种解决方案:

提供本地HTML

如果你现在想在你的页面上嵌入一个带有JavaScript的HTML页面,最简单的方法是将你的HTML文件保存到笔记本电脑的目录中,然后按如下方式加载HTML:

from IPython.display import IFrame

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

提供远程HTML

如果你更喜欢托管解决方案,你可以将你的HTML页面上传到S3中的Amazon Web Services“bucket”中,更改桶上的设置,使桶托管一个静态网站,然后在你的笔记本中使用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>

首先,代码:

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)

一些简单的笔记:

You can generally just use inline HTML for simple items. If you are rendering a framework, like a large JavaScript visualization framework, you may need to use an IFrame. Its hard enough for Jupyter to run in a browser without random HTML embedded. The strange parameter, metadata=dict(isolated=True) does not isolate the result in an IFrame, as older documentation suggests. It appears to prevent clear-fix from resetting everything. The flag is no longer documented: I just found using it allowed certain display: grid styles to correctly render. This IFrame solution writes to a temporary file. You could use a data uri as described here but it makes debugging your output difficult. The Jupyter IFrame function does not take a data or srcdoc attribute. The tempfile module creations are not sharable to another process, hence the random_name(). If you use the HTML class with an IFrame in it, you get a warning. This may be only once per session. You can use HTML('Hello, <b>world</b>') at top level of cell and its return value will render. Within a function, use display(HTML(...)) as is done above. This also allows you to mix display and print calls freely. Oddly, IFrames are indented slightly more than inline HTML.