IPython工作原理

news2024/11/17 10:26:39

IPython工作原理

在这里插入图片描述

文章目录

    • IPython是什么?
    • IPython工作原理
      • IPython控制台
      • IPython内核
    • 实现一个简单的包装内核
    • 代码在IPython内核中的执行流程

IPython是什么?

Python最有用的功能之一就是它的交互式解释器。交互式编程允许我们非常快速地执行代码片段、测试验证想法,而无需像大多数其他编程语言那样要先创建项目、创建源文件,然后才能执行。然而,Python自带的解释器对使用交互式解释器有一定的限制。IPython的出现就是为了弥补这些不足。

IPython的目标是为交互式和探索性计算创建一个全面、完整、易用的环境。为此IPython提供了三大组件:

  • 一个加强版交互式Python命令行工具;
  • 一种解耦的双进程通信模型,允许多个客户端连接到计算内核。著名的Jupyter就是基于这个特性开发的;
  • 一个交互式并行计算架构,现在已经融合到ipyparallel 包中。

IPython是完全开源的,大家可以在这里获取到IPython的源代码。

IPython安装也非常简单,只需要执行下面的命令即可:

$ pip install ipython

当然我们也可以只安装IPython内核,供Jupyter使用:

$ python -m pip install ipykernel

IPython工作原理

IPython控制台

当我们在控制台输入ipython命令后,我们就进入了IPython原生的控制台界面,你将看到类似下面的控制台交互界面:

在这里插入图片描述

此时我们就可以直接在控制台中输入要运行的Python代码。

IPython控制台的核心引擎其实非常简单,类似下面的代码功能:

while True:
    code = input(">>> ")
    exec(code)

当然,IPython的实际代码要不这复杂,以为它还会处理多行代码、代码补全、历史记录、魔法命令等功能。但核心思路是一样的,都是提示用户输入代码,然后再同一进程执行所输入的代码。这其实就是REPL要做的事。

REPL是Read-Eval-Print-Loop的首字母,它是交互式编程的基础模型。

IPython内核

除了IPython自带的控制台,IPython还有很多第三方交互界面和工具,其中最著名的当属Jupyter Notebook。这些第三方界面要想驱动IPython工作就需要使用IPython内核。IPython内核运行在一个单独的进程中,负责运行用户的代码。前端通过ZeroMQ将消息以JSON格式发送给IPython内核,并通过 ZeroMQ socket与IPython内核保持通信,通信协议可以参考Jupyter消息传递。

IPython内核的核心执行机制与IPython终端共享:

在这里插入图片描述

图1. 执行器共享

一个内核进程可以同时连接多个前端,这是多个前端访问到的是同样的内存数据。

将内核和前端解耦的优点非常明显:

  1. 可以基于同一内核轻松开发不同的前端;
  2. 可以为同一前端提供其他语言的内核,Jupyter支持多种语言就是这一设计的直接受益者。

目前有两种方式开发其他语言的内核:

  • 包装IPython内核,重用IPython的通信机制,只实现核心执行部分;
  • 原生内核,用目标语言重新实现执行部分和通信部分。

在这里插入图片描述

图2. 包装内核 vs 原生内核

很明显,包装内核实现起来会更简单,因此如果目标语言与Python交互良好(比如octave_kernel),或者目标语言不方便实现通信的(比如bash_kernel),用包装内核实现会简单快速很多。

实现一个简单的包装内核

用包装IPython内核的方式实现新内核非常简单,关键步骤就是声明一个类,继承自ipykernel.kernelbase.Kernel,然后实现相应的属性和方法。

其中必须提供的属性如下:

属性名类型说明
implementationstr内核名称
implementation_versionstr内核版本
bannerstr控制台启动时输入提示符出现前展示给用户的信息
languagestr内核语言
language_versionstr内核语言版本
language_infodict内核语言信息,字典类型,需要包括mimetype 目标语言的mimetype 和 file_extension 目标语言源代码文件后缀名称。

必须实现的方法只有一个 do_execute(code, silent, store_history=True, user_expressions=None, allow_stdin=False),用于执行用户代码。参数含义如下:

参数名类型说明
codestring要执行的代码
silentbool是否显示输出
store_historybool是否将代码存入历史库中并增加执行计数。如果silent为True,则store_history默认为False。
user_expressionsdict代码执行完后,对要求值的表达式命名
allow_stdinbool前端是否可以根据请求提供输入

do_execute方法返回一个字典,其中需要包含的字段在 Execution results 中有详细的介绍。要显示输出,可以使用send_response()发送消息。有关各消息类型的详细信息,请参阅IPython中的消息传递。

内核写好后可以用IPKernelApplaunch_instance方法启动内核,传入我们自定义的内核类即可:

if __name__ == '__main__':
    from ipykernel.kernelapp import IPKernelApp
    IPKernelApp.launch_instance(kernel_class=MyKernel)

下面是一个完整的包装内核的实现例子:

from ipykernel.kernelbase import Kernel

class EchoKernel(Kernel):
    implementation = 'Echo'
    implementation_version = '1.0'
    language = 'no-op'
    language_version = '0.1'
    language_info = {'mimetype': 'text/plain'}
    banner = "Echo kernel - as useful as a parrot"

    def do_execute(self, code, silent, store_history=True, user_expressions=None,
                   allow_stdin=False):
        if not silent:
            stream_content = {'name': 'stdout', 'text': code}
            self.send_response(self.iopub_socket, 'stream', stream_content)

        return {'status': 'ok',
                # The base class increments the execution count
                'execution_count': self.execution_count,
                'payload': [],
                'user_expressions': {},
               }

if __name__ == '__main__':
    from ipykernel.kernelapp import IPKernelApp
    IPKernelApp.launch_instance(kernel_class=EchoKernel)

上面的代码简单地将用户输入直接输出出来。

除此之外,还需要提供一个内核描述文件用于指定如何运行内核

{"argv":["python","-m","echokernel", "-f", "{connection_file}"],
 "display_name":"Echo"
}

代码在IPython内核中的执行流程

当IPython内核收到代码执行请求时,会按照一下步骤处理:

  1. 触发pre_execute事件;
  2. 如果silence不为True,则触发pre_run_cell事件;
  3. 执行run_cell方法,run_cell方法会对传入代码进行预处理,然后编译执行它。这是整个执行流程的主体,后面会详细讲解这个过程;
  4. 如果执行成功,定义在user_expressions中的表达式会触发求值,这样做的好处是可以确保表达式中的任何错误都不会影响主代码的执行;
  5. 触发post_execute事件;
  6. 如果silence不为True,则触发post_run_cell事件。

其中代码的执行部分又会分2个阶段:首先IPython.core.inputtransformer2会将代码块中的%magic!system命令展开转换成python代码;然后用Python的 compile()方法编译并执行代码。

在这里插入图片描述

图3. IPython代码执行流程

Python的compile()方法提供了mode参数可以选择编译方式,有三种方式可选:

single

对于单一交互语句有效(尽管代码可以包含多行,例如for循环)。在这种模式下编译时,生成的字节码包含特殊指令,这些指令会触发对代码块中返回的任何表达式调用sys.displayhook()。这意味着一条语句实际上可以产生多次sys.displayhook()调用,例如下面的代码:

for i in range(10):
    i**2

表达式包含在循环中,且表达式的值没有赋给任何变量,此时将调用10次sys.displayhook()

exec

编译任意数量的代码,pyhton模块就是用这种方式编译的。这种编译模式不会调用sys.displayhook()

eval

执行单一表达式,不会调用sys.displayhook()

传入的源代码会被划分为若干独立的代码块,每个块确保可以使用single模式编译。如果只有一个代码块,那就用single模式编译;如果有多个代码块,则按照如下逻辑执行:

  • 如果最后一个代码块不超过两行,则最后一个代码块之前的代码用exec模式编译,只有最后一个代码块用single模式编译。这样可以很容易地在末尾输入简单表达式查看计算结果。
  • 如果最优一个代码块大于两行,则全部用exec模式编译。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/55391.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[附源码]计算机毕业设计在线教育系统Springboot程序

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

详解 Intersection Observer API ( 交叉观察器 )

文章目录一、介绍二、兼容性三、内置方法/属性四、使用五、相关链接一、介绍 Intersection Observer API 提供了一种方法可以监听目标元素是否展示到视口(viewport),常见的需求场景: 图片懒加载滚动动画… 上述的需求&#xff…

基于PHP+MySQL医院门诊缴费系统的设计与实现

本医院门诊缴费系统可以说是一个综合性的医院门诊缴费系统,这它包含了挂号管理,医生信息管理,药品信息管理,患者信息管理,住院信息挂了,收费信息管理等多种功能,因而具有一定的实用性。本站是一个B/S模式系统,开发采用了目前流行的PHP技术。系统界面友好,操作简单,比较实用。 本…

浅谈小程序开源业务架构建设之路

一、业务介绍 1.1 小程序开源整体介绍 百度从做智能小程序的第一天开始就打造真正开源开放的生态,我们的愿景是:定义移动时代最佳体验,建设智能小程序行业标准,打破孤岛,共建开源、开放、繁荣的小程序行业生态。百度…

element-ui实现一个动态布局的对话框

前言:在工作中有各种各样的对话框,最多就是填写信息这些的,一般这样的内容都是el-input输入框,el-select选择框等等之内的,这时我们就可以封装成一个组件,想要什么内容就传一个json配置,像其他组…

适合Python初学者阅读的Github开源代码

程序员宝藏库:https://gitee.com/sharetech_lee/CS-Books-Store 你想要的,这里都有! Python作为一门热门的编程语言,在Github上想要找Python项目可以说是「多如牛毛」。 无论是Star数量还是项目数量,都稳居前3名。 项…

5分钟搭建一个粗粒度「视频去重」系统

Jupyter Notebook 教程: How to Build a Video Deduplication System 「视频去重」可以在海量的视频数据中实现侵权片段或者删除掉重复冗余的内容 。随着抖音、快手、Bilibili 等视频平台的兴起和火爆,类似视频这样的非结构化数据在数量上有了极大的增长。 视频平台…

【数据可视化】第四章—— 基于pandas的数据可视化(pandas基本操作)

图形绘制的代码:链接:https://pan.baidu.com/s/1pgS60sry6XDILIhth8bAvA?pwdabcd 提取码:abcd 文章目录1. Pandas库的数据运算1.1 方法形式的运算1.2 比较运算法则1.3 排序2. 基本统计分析函数2.1 基本统计分析函数2.2 累计统计分析函数2.3 …

[附源码]计算机毕业设计JAVA学生量化考核管理系统

[附源码]计算机毕业设计JAVA学生量化考核管理系统 项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM my…

基于PHP+MySQL高校毕业设计管理系统的设计与实现

直以来我国领导人提倡以人为本的治国方案,而大学是未来人才的培养基地,如何能够更好的对高校毕业设计信息进行管理,是很多高校一直在研究的一个问题,只有更加科学的对高校毕业设计信息进行管理,才能够更加积极的培养国家的栋梁之才。 管理员部分功能 1:教师新管理…

第二十二章《记事本》第1节:记事本项目简介

记事本软件能够打开、编辑、保存各种类型的文本文档,也能在文本文档中查找特定的关键字,此外在还能设定文本文档的字体、字号以及风格等。 22.1.1记事本功能简介 记事本软件的运行结果如图22-1所示。 图22-1记事本软件界面 从图21-1可以看到:记事本程序运行开始后,在没有…

OpenFeign动态代理、源码分析

1、OpenFeign概述 OpenFeign 组件的前身是 Netflix Feign 项目,由 Netflix 公司开发。后来 Feign 项目被贡献给了开源组织,随后Feign退出历史舞台。 OpenFeign是Spring Cloud在Feign的基础上支持了SpringMVC的注解,如RequestMapping等等。O…

基于springboot的家装平台设计与实现

项目描述 临近学期结束,还是毕业设计,你还在做java程序网络编程,期末作业,老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下,你想解决的问…

牛客练习赛106 三子棋

牛客练习赛106 三子棋 2022.12.02 题目描述 给定一个 333 \times 333 的棋盘,共有 3393 \times 3 9339 个格子,初始时每个格子均没有放置棋子。 A 和 B 轮流行动,每次行动的人,必须在当前棋盘上选择一个没有放置棋子的格子…

基于PHP+MySQL学生成绩管理系统的设计与实现

基于PHP的学生成绩管理系统主要高校内部提供服务,系统分为管理员,教师用户和学生用户三部分。 在基于PHP的学生成绩管理系统中分为管理员用户,教师用户和学生用户三部分,其中管理员用户主要是用来管理教师信息,学生信息,课程信息,专业信息和班级信息等内容,教师用户主要是用来管…

业务流程管理的未来趋势:个性化定制

自进入互联网时代以来、甚至更早,无论是从物质还是精神层面,“个性化”已经成为大众所普遍追求的东西。个性化定制允许买家按照自身偏好对产品进行二次改造,例如许多汽车品牌,就可以根据车主的想法来实现定制。 其实,…

Spring Boot 集成 EasyExcel 3.x 优雅实现Excel导入导出

Spring Boot 集成 EasyExcel 3.x 本章节将介绍 Spring Boot 集成 EasyExcel(优雅实现Excel导入导出)。 🤖 Spring Boot 2.x 实践案例(代码仓库) 介绍 EasyExcel 是一个基于 Java 的、快速、简洁、解决大文件内存溢出的…

CSS盒子模型(上)

🍓个人主页:bit.. 🍒系列专栏:Linux(Ubuntu)入门必看 C语言刷题 数据结构与算法 HTML和CSS3 目录 1.盒子模型 1.2盒子模型(Box Model)组成 1.3边框(border) 1.4 表格的…

这才是Git的正确学习方式

程序员宝藏库:https://gitee.com/sharetech_lee/CS-Books-Store 你想要的,这里都有! 我认为学习一门知识最怕的就是一知半解、草草了事,对于Git这种工具类更是如此。 有很多同学工作后,日常用到git clone、git add、g…

ubuntu18.04下cmake的安装

一.使用安装命令 sudo apt install cmake这种方式安装最为简单,但是,这种方式安装的不是最新版本的Cmake。 我此次安装cmake是因为要编译fastdds,其实之前系统中有cmake,但是在编译fastdds的过程中依然提示我: CMake…