# 操作系统如何运行程序 人和操作系统如何交互?最早Ken Thompson设计Unix的时候,使用的是命令解释器,命令解释器接受用户的命令,然后解释他们并执行。 `Shell`是人和机器交互的界面,分为`GUI`和`命令行(CLI)`两种方式,这里重点介绍命令行的方式。概念`Shell`路易斯·普赞(Louis Pouzin)在1964年至1965年间首次提出,随后在Multics(MULTiplexed Information and Computing System)项目中首次被实现出来。肯·汤普逊(Ken Thompson)以Multics上的shell为范本实现的第一个Unix壳层(Unix shell):`Thompson shell`。AT&T贝尔实验室的史蒂夫·伯恩在1977年实现了`Bourne shell`,或`sh`,它是Version 7 Unix默认的Unix shell,替代执行文件同为sh的Thompson shell。微软的Windows操作系统也提供了命令行壳层的功能,它们是Windows 95 / 98下的`command.com`、Windows NT内核下的`cmd.exe`以及`PowerShell`。 下面的`Python 列表`包含了Unix系统常见的`shell`: ```python shells = [ 'Bourne shell(sh)', 'Almquist shell(ash)', 'Debian Almquist shell(dash)', 'Bourne-Again shell(bash)', 'Korn shell(ksh)', 'Z shell(zsh)', 'C shell(csh)', 'TENEX C shell(tcsh)', 'EMACS shell (eshell)', 'Es shell(es)', 'esh (Unix) – Easy Shell', 'friendly interactive shell(fish)', 'rc shell(rc)– shell for Plan 9 from Bell Labs and Unix', 'scsh(Scheme Shell)', 'Stand-alone Shell(sash)', 'BeanShell(bsh,bsh.Interpreter , bsh.Console)', 'Rhino JavaScript壳层(org.mozilla.javascript.tools.shell.Main)' ] ``` 通过shell,我们可以让操作系统执行Python程序。而Python是解释型语言,源代码不是直接翻译成机器语言,而是先翻译成中间代码,再由解释器对中间代码进行解释运行。有两种执行Python程序的方式,下面的`Python 字典`包含了这两种方式的信息: ```python run = { "repl": { "title": "交互式编程( Interactive )", "desc": [ "打开终端,输入 python 回车", "进入 Python 交互式命令行", "输入 print('monkey king is coding!')" ] }, "source": { "title": "Python 源代源文件( File )", "desc": [ "使用你喜欢的编辑器拷贝本练习的代码, 保存为run.py", "打开终端,cd 到 run.py 保存的目录", "输入 python run.py" ] } } ``` ![](https://userblink.csdnimg.cn/20211123/huanhuilong/pic/8555cd59ff00168ff58c23235a325867-0.png) 交互式命令行通常也称`REPL`,表示`Read-Eval-Print-Loop`,顾名思义是:`读取`-`评估`-`打印`-`循环`的意思。当你在`shell`环境里输入`python`并回车,就进入了`Python的REPL环境`,程序总是: 1. 等待用户输入 Python 代码 2. 当收到回车信号后就读取(`Read`)用户输入的 Python 代码 3. 解释读取到的 Python 代码(`Eval`) 4. 打印Python 代码的解释结果(`Print`) 5. 回到步骤1,循环(`Loop`)该过程 实际上,我们在之前的习题里已经见过这样的程序,经过重新认识后,现在可以再次编写一个这样的`REPL`程序,**功能需求如下**: * 提示用户选择想要了解的Python 的两种运行方式 * 用户选择后输出对应Python 运行方式的基本说明,如果用户输入错误则提示后让用户重新选择 * 循环该过程直到用户输入`q`退出 * 最后输出用户学习了几种运行方式 基本代码框架如下: ```python if __name__ == '__main__': run = { "i": { "title": "交互式编程( Interactive )", "desc": [ "打开终端,输入 python 回车", "进入 Python 交互式命令行", "输入 print('monkey king is coding!')" ] }, "f": { "title": "Python 源代源文件( File )", "desc": [ "使用你喜欢的编辑器拷贝本练习的代码, 保存为run.py", "打开终端,cd 到 run.py 保存的目录", "输入 python run.py" ] } } print("有两种基本的方式运行 Python") for s in run: item = run.get(s) print("* {}: {}".format(s, item['title'])) has_learn_i = False has_learn_f = False # TODO(You): 请在此实现代码 if has_learn_i and has_learn_f: print("[2/2]您已完成两种 Python 运行方式的学习") elif has_learn_f: print("[1/2]您已完成 Python 源代码方式运行学习") elif has_learn_i: print("[1/2]您已完成 Python 交互式命令行运行学习") else: print("[0/2]您似乎跳过了运行方式的学习?期待下次光临!") ``` 程序的示例操作过程如下: ```bash 有两种基本的方式运行 Python * repl: 交互式编程( Interactive ) * source: Python 源代源文件( File ) 请选择你想了解的 Python 运行方式(输入:r/s选择,输入 q 退出):r 0. 打开终端,输入 python 回车 1. 进入 Python 交互式命令行 2. 输入 print('monkey king is coding!') 请选择你想了解的 Python 运行方式(输入:r/s选择,输入 q 退出):s 0. 使用你喜欢的编辑器拷贝本练习的代码, 保存为run.py 1. 打开终端,cd 到 run.py 保存的目录 2. 输入 python run.py 请选择你想了解的 Python 运行方式(输入:r/s选择,输入 q 退出):q [2/2]您已完成两种 Python 运行方式的学习 ``` 以下选项是对代码中`TODO`部分的多种实现,你能找出实现错误的选项吗? ## template ```python if __name__ == '__main__': run = { "repl": { "title": "交互式编程( Interactive )", "desc": [ "打开终端,输入 python 回车", "进入 Python 交互式命令行", "输入 print('monkey king is coding!')" ] }, "source": { "title": "Python 源代源文件( File )", "desc": [ "使用你喜欢的编辑器拷贝本练习的代码, 保存为run.py", "打开终端,cd 到 run.py 保存的目录", "输入 python run.py" ] } } print("有两种基本的方式运行 Python") shoutcut_keys = {} for name in run: key = name[0].lower() shoutcut_keys[key] = name item = run.get(name) print("* {}: {}".format(name, item['title'])) has_learn_repl = False has_learn_source = False while True: ret = input("请选择你想了解的 Python 运行方式(输入:r/s选择,输入 q 退出):") if ret == 'q': break elif ret == 'r': has_learn_repl = True elif ret == 's': has_learn_source = True name = shoutcut_keys.get(ret) if name is None: print("[错误] 不支持的运行方式") else: item = run.get(name) desc = item['desc'] for i in range(0, len(desc)): print("{}. {}".format(i, desc[i])) if has_learn_repl and has_learn_source: print("[2/2]您已完成两种 Python 运行方式的学习") elif has_learn_source: print("[1/2]您已完成 Python 源代码方式运行学习") elif has_learn_repl: print("[1/2]您已完成 Python 交互式命令行运行学习") else: print("[0/2]您似乎跳过了运行方式的学习?期待下次光临!") ``` ## 答案 ```python while True: ret = input("请选择你想了解的 Python 运行方式(输入:r/s选择,输入 q 退出):") if ret == 'r' or ret == 's': has_learn_repl = ret=='r' has_learn_source = ret=='s' desc = run.get(shoutcut_keys.get(ret))['desc'] for i in range(0, len(desc)): print("{}. {}".format(i, desc[i])) elif ret != 'q': print("[错误] 不支持的运行方式") break else: pass ``` ## 选项 ### 普通实现 ```python while True: ret = input("请选择你想了解的 Python 运行方式(输入:r/s选择,输入 q 退出):") if ret == 'q': break elif ret == 'r': has_learn_repl = True elif ret == 's': has_learn_source = True name = shoutcut_keys.get(ret) if name is None: print("[错误] 不支持的运行方式") else: item = run.get(name) desc = item['desc'] for i in range(0, len(desc)): print("{}. {}".format(i, desc[i])) ``` ### 合并错误处理 ```python while True: ret = input("请选择你想了解的 Python 运行方式(输入:r/s选择,输入 q 退出):") name = shoutcut_keys.get(ret) if name is None: if ret=='q': break else: print("[错误] 不支持的运行方式") continue has_learn_repl = ret=='r' has_learn_source = ret=='s' desc = run.get(name)['desc'] for i in range(0, len(desc)): print("{}. {}".format(i, desc[i])) ``` ### 极简模式 ```python while True: ret = input("请选择你想了解的 Python 运行方式(输入:r/s选择,输入 q 退出):") if ret == 'r' or ret == 's': if ret=='r': has_learn_repl = True else: has_learn_source = True item = run.get(shoutcut_keys.get(ret)) desc = item['desc'] for i in range(0, len(desc)): print("{}. {}".format(i, desc[i])) elif ret == 'q': break else: print("[错误] 不支持的运行方式") ```