鱼C论坛

 找回密码
 立即注册
查看: 146|回复: 9

[技术交流] 用 python 模拟 python 交互解释器

[复制链接]
回帖奖励 18 鱼币 回复本帖可获得 3 鱼币奖励! 每人限 1 次(中奖概率 60%)
发表于 4 天前 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 smallwh 于 2024-9-17 11:43 编辑

python 你不知道的模块
——用 python 模拟 python 交互解释器

先宣布一个重大消息:
2024年9月16日,python 开始了 3.14 版本的内测,详情见此

python314.gif


玩笑开到这里。其实,这是一个用 python 写的交互解释器。而且非常简单,学会了便可以去坑小伙伴了。




一、准备工作:
1. python 环境
2. 有或有过想用 python 写交互解释器的冲动


二、分析:
1.本次要用到的模块有 sys 和 code ,两者都是 python 内置模块,都由 python 语言编写。
code 模块是对 codeop 模块的封装,不过在此我们不需要了解 codeop 模块。

2. code 模块共有两个类和两个函数,功能对应如下:
名称作用
InteractiveInterpreter这个类处理解释器状态(即用户的命名空间)。它不处理缓冲、输入提示符或着输入文件名。
InteractiveConsole这个类尽可能模拟交互式解释器的行为,建立在 InteractiveInterpreter 的基础上,并有输入缓冲。
interact最终模拟解释器的函数。它会创建一个新的 InteractiveConsole 实例。
compile_command判断代码是否完整有效的函数。

*名词的解释:
名称解释
解释器状态就是预先定义好的一些变量和函数,比如标准解释器中 __name__ 为 '__main__'
输入提示符举两个例子: >>> 和 ... 。熟悉吧?
输入文件名Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
    1/0
ZeroDivisionError: division by zero
<stdin>就是输入文件名


3. interact 函数更方便、更简单。
interact(banner=None, readfunc=None, local=None, exitmsg=None)
banner:解释器一开始打印的消息,传入一个字符串。默认值为尽可能模拟交互解释器的行为,但因为模拟得太像加了注意区分的提示。
readfunc:用来读取输入的函数,默认是 InteractiveConsole.raw_input 。
local:用户的命名空间,传入一个字典,默认为 {"__name__": "__console__", "__doc__": None} 。
exitmsg:解释器退出时打印的消息,传入一个字符串。默认值为"now exiting InteractiveConsole..."。
注意,调用 exit() 不算作解释器退出。必须引发 EOFErroe 才会打印该消息。在 windows 控制台中运行时,按下 CTRL+Z 后回车可引发。


三、实践:
1.
import code
code.interact()
#最简单的交互式解释器
2.上面的效果和 python 交互式解释器还有点区别。下面来一个更像的。
我们先来看一下 interact() 的实现(删减掉了注释)
def interact(banner=None, readfunc=None, local=None, exitmsg=None):
    console = InteractiveConsole(local)
    if readfunc is not None:
        console.raw_input = readfunc
    else:
        try:
            import readline #Windows该模块不可用
        except ImportError:
            pass
    console.interact(banner, exitmsg)
我们要让开始和结束时打印的信息完全相同。同时要让报错信息也相同。
对代码进一步化简,修改(比如删掉”一定“不会跑的 if 语句):
import code
import sys

banner = """Python %s on %s
Type "help", "copyright", "credits" or "license" for more information.""" %(sys.version, sys.platform)
local = {"__name__": "__main__", "__doc__": None}
exitmsg = ''

console = code.InteractiveConsole(local,filename='<stdin>')
console.interact(banner,exitmsg)
保持为 .py 文件,运行,看看你能不能找出有什么区别。
(当然 idle 里面颜色会不一样)
效果.jpg

3.模拟 python3.14 。
import code
import sys
sys.version = 'Python 3.14.1 (tags/v3.14.1:580fbb0, Sep 16 2024, 15:57:54) [MSC v.1924 64 bit (AMD64)]'

banner = """Python %s on %s
Type "help", "copyright", "credits" or "license" for more information.""" %(sys.version, sys.platform)
local = {"__name__": "__main__", "__doc__": None}
exitmsg = ''

console = code.InteractiveConsole(local,filename='<stdin>')
console.interact(banner,exitmsg)


四、总结:
code 模块里类的方法多数是为 InteractiveConsole.interact 服务的,单独没什么大用途。模块很小,可以自己看源码、帮助手册,找到更多的玩法。

追根溯源,输入的代码是用内置函数 compile 编译的。因为 eval 函数不能运行代码,exec 函数不能求值,所以许多自己写交互式解释器的都失败了。而 compile 编译后得到一个代码对象后再用 exec 运行,可以克服两者的缺点。python 的内置模块和内置函数,就像一片藏有许多美丽贝壳的沙滩,而我们从没有完整地探索过。如果你知道有哪些实用或好玩的内置函数和模块,也欢迎分享。

最后,感谢大家和鱼C这个平台,如果有什么问题和错误,欢迎提问、指出。
祝大家中秋节快乐!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 4 天前 | 显示全部楼层
好玩,

评分

参与人数 1鱼币 +2 收起 理由
smallwh + 2

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 4 天前 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 4 天前 | 显示全部楼层
嘿嘿,谢谢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 4 天前 | 显示全部楼层

回帖奖励 +3 鱼币

厉害
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 3 天前 | 显示全部楼层

回帖奖励 +3 鱼币

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 前天 08:50 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 前天 09:05 | 显示全部楼层

回帖奖励 +3 鱼币

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 前天 09:24 | 显示全部楼层
1
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 昨天 16:09 | 显示全部楼层

回帖奖励 +3 鱼币

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-9-21 11:17

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表