smallwh 发表于 2024-9-17 11:41:13

用 python 模拟 python 交互解释器

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

python 你不知道的模块
——用 python 模拟 python 交互解释器
先宣布一个重大消息:
2024年9月16日,python 开始了 3.14 版本的内测,详情见此




玩笑开到这里。其实,这是一个用 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 里面颜色会不一样)


3.模拟 python3.14 。
import code
import sys
sys.version = 'Python 3.14.1 (tags/v3.14.1:580fbb0, Sep 16 2024, 15:57:54) '

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这个平台,如果有什么问题和错误,欢迎提问、指出。
祝大家中秋节快乐!

某一个“天” 发表于 2024-9-17 12:35:39

好玩,

某一个“天” 发表于 2024-9-17 12:36:18

{:10_256:}

某一个“天” 发表于 2024-9-17 19:24:04

嘿嘿,谢谢

芜湖666 发表于 2024-9-17 20:12:53

厉害

很cool的阳 发表于 2024-9-18 09:57:05

{:7_113:}

简柠啦 发表于 2024-9-19 08:50:01

{:10_256:}{:10_256:}

kerln888 发表于 2024-9-19 09:05:59

{:10_279:}{:10_279:}{:10_279:}{:10_279:}{:10_279:}

咔咔咔米 发表于 2024-9-19 09:24:50

1

trinityee 发表于 2024-9-20 16:09:33

{:10_254:}{:10_254:}

XiaoMengXin-1 发表于 2024-9-22 14:56:32

鱼币

XiaoMengXin-1 发表于 2024-9-22 14:57:02

鱼币

spt1314 发表于 2024-9-22 21:36:21

先了解再学习

loveKYF 发表于 2024-9-22 21:37:41

膜拜大佬

林木荟蔚 发表于 2024-9-22 21:38:23

内容很有趣

格子penbeat 发表于 2024-9-22 21:39:23

哈哈哈,真逗,我反正没想过...

泼墨染笛香 发表于 2024-9-22 21:40:09

Python交互式解释器是一种REPL(Read-Eval-Print Loop)环境。它会读取用户输入的代码,执行代码,并输出结果,随后等待下一个用户输入。这种交互方式使得Python非常适合快速原型开发和实验。

smallsnail07 发表于 2024-9-22 21:42:47

学习学习

想个好名字@ 发表于 2024-9-22 21:43:39

继续学习!

yasi 发表于 2024-9-22 21:43:56

学习学习,明天就动起来
页: [1] 2 3
查看完整版本: 用 python 模拟 python 交互解释器