马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本帖最后由 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) [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这个平台,如果有什么问题和错误,欢迎提问、指出。
祝大家中秋节快乐! |