Python 2 raw_input()与Python 3 input()有什么区别

小岛来信
小岛来信
发布时间:2026-10-10| 3人浏览过
原创
在控制台获取用户输入时,Python 2 与 Python 3 的内置函数设计存在根本性的机制演进。核心区别在于:Python 2 中同时存在 raw_input() 与 input() 两个函数,其中 raw_input() 将键盘输入完整作为原始字符串返回,而 input() 会在内部隐式调用 eval() 对输入内容进行动态求值;到了 Python 3,危险的自动求值机制被彻底废弃,旧版 raw_input() 被移除,其原有的安全读取功能直接由 Python 3 的 input() 继承,并固定返回原生 Unicode 字符串。

核心区别概览与函数映射关系

对于初学者与从旧版本迁移代码的开发者而言,混淆输入函数不仅会导致程序逻辑异常,更可能埋下严重的系统安全漏洞。Python 语言在由 2.x 向 3.x 版本演进的过程中,针对输入接口做出了“去除隐式求值、强化数据安全”的重构。

函数名称 支持环境 底层运行逻辑 返回值数据类型 安全性评价 典型处理方式
raw_input() Python 2.x 读取输入并剥离末尾换行符,原样返回文本 str(8 位字节串) 安全 无注入风险 需手动使用 int() 等显式转换类型
input() Python 2.x 等价于 eval(raw_input()) 动态计算 取决于输入计算结果的动态类型 极高危 存在任意代码执行漏洞 易受恶意输入攻击,现代开发坚决弃用
input() Python 3.x 完全继承旧版 raw_input() 的安全机制 str(原生 Unicode 字符串) 安全 纯数据输入 纯文本直接使用,数值需配合显式转换
raw_input() Python 3.x 该函数已被完全删除,调用抛出异常 不适用(抛出 NameError) 不适用 代码迁移时直接全局替换为 input()

通过下方的结构关系图,可以直观理清两个版本之间输入函数的废弃、继承与演进逻辑:

Python 2 raw_input()与Python 3 input()有什么区别
图 1:Python 2 到 Python 3 输入函数的职责继承与机制重构路径

Python 2 中 raw_input() 与 input() 的机制差异

在 Python 2 环境中,设计者最初设想:为开发者提供一个“直接输入文本”的函数(raw_input),同时提供一个“能够直接识别数字和数据结构”的便捷函数(input)。然而,这种设计带来了严重的安全与逻辑缺陷。

1. raw_input() 的原样读取机制

raw_input() 是纯粹的标准输入流读取工具。它会等待用户在控制台键入字符,直至按下回车键。该函数会剥离行尾的换行符 \n,并将剩余内容直接包装为一个标准的 8 位字符串(str)返回给调用者。

# Python 2 环境演示 raw_input() text = raw_input("请输入内容: ") print type(text) # 输出: <type 'str'> print repr(text) # 无论输入何种内容,均原样以字符串输出

例如,当用户在提示符后键入 123 时,raw_input() 返回的是字符串 '123';键入 1 + 2 时,返回的是字符串 '1 + 2'。它绝不会尝试去计算或解析输入内容,因此数据输入与代码执行边界清晰。

2. Python 2 input() 的隐式动态求值漏洞

与 raw_input() 不同,Python 2 中的 input() 并不是一个独立实现的输入解析器,它的底层逻辑完全等价于:

# Python 2 中 input() 的底层等价形式 def input(prompt=None): return eval(raw_input(prompt))

这意味着任何通过 input() 键入的内容,都会被直接放入 Python 表达式解析器中进行计算。这一机制引发了三大严重问题:

  • 输入字符串必须加引号:如果用户希望输入一个普通单词(如 hello),直接输入会导致 Python 尝试寻找名为 hello 的变量,进而抛出 NameError: name 'hello' is not defined。用户必须繁琐地手动键入 "hello"。
  • 数据类型不稳定:如果程序期望获取一个数值,用户输入 100 得到整型,输入 [1, 2] 得到列表,输入 3.14 得到浮点型。如果用户输入了不合法的表达式,程序将直接崩溃。
  • 灾难性的代码执行安全风险:由于 eval() 拥有完整的表达式求值权限,若恶意攻击者在终端输入系统调用代码(例如 __import__('os').system('rm -rf /')),Python 会立即执行该系统命令,从而引发严重的系统越权与破坏。
Python 2 raw_input()与Python 3 input()有什么区别
图 2:Python 2 中 raw_input() 与 input() 的底层数据流与安全边界对比

Python 3 统一为 input() 的设计理念与类型特征

基于 Python 哲学中“显式优于隐式(Explicit is better than implicit)”与“安全性高于微弱便利性”的原则,Python 3 对控制台输入体系做出了彻底重塑:

1. 剔除隐式求值,确立纯文本安全契约

在 Python 3 中,旧版具备自动执行表达式特性的 input() 被彻底废除。取而代之的是:将原 raw_input() 的行为重命名为 input(),并完全移除了 raw_input 这一函数标识符。

在 Python 3 中执行 data = input(),无论用户在键盘上输入什么字符(数字、字母、符号、Python 代码甚至换行符),程序一律将其视为字面文本,绝不进行隐式求值。

2. 返回值底层类型由字节串升级为 Unicode

除了执行机制的变化,返回值的底层类型系统也迎来了关键升级:

  • Python 2 的 raw_input():返回的是 8 位的 str 类型,其实质等价于字节串(Byte String)。若终端包含中文字符,获取到的实质是一串未经解码的机器字节(例如 UTF-8 或 GBK 编码序列),进行切片、计数或拼接时极易发生乱码。
  • Python 3 的 input():返回的是原生支持 Unicode 的 str 字符串。Python 解释器在接收到终端输入流时,会自动依据系统当前的控制台编码(如 UTF-8)完成无缝解码。中文字符在长度计算、切片与匹配时均被作为统一的字符单元处理,彻底规避了中文乱码陷阱。

3. 规范的数据类型显式转换范式

在 Python 3 中,由于 input() 始终返回字符串,当业务场景需要数值或其他结构时,开发者必须显式进行类型转换,并配合异常处理确保程序稳健:

import ast # 场景一:转换为整数(结合异常处理) raw_age = input("请输入年龄: ") try: age = int(raw_age) print("年龄记录成功:", age) except ValueError: print("输入格式错误:请输入有效的纯数字!") # 场景二:转换为浮点数 raw_price = input("请输入单价: ") try: price = float(raw_price) print("商品价格:", price) except ValueError: print("输入格式错误:请输入有效的数值!") # 场景三:安全解析字面量结构(如输入列表 [1, 2, 3] 或字典) # 注意:严禁使用 eval(input())!应当使用 ast.literal_eval() raw_list = input("请输入数据列表: ") try: parsed_data = ast.literal_eval(raw_list) print("解析得到的数据类型:", type(parsed_data)) except (ValueError, SyntaxError): print("输入格式错误:必须为合法的 Python 字面量结构!")
Python 2 raw_input()与Python 3 input()有什么区别
图 3:Python 3 终端输入安全规范与多业务场景类型转换标准架构

跨版本兼容处理与工程迁移指南

在进行项目维护或代码重构时,开发者经常面临两种典型需求:一是编写同时兼容 Python 2 和 Python 3 的跨环境运行脚本;二是从旧版 Python 2 代码库向 Python 3 迁移。针对这两种场景,有明确的标准解决方案。

1. 编写跨版本兼容输入代码

如果脚本必须同时在尚未退役的 Python 2 嵌入式环境与现代 Python 3 环境下运行,可以在模块头部使用内置异常捕获机制进行函数重绑定:

# 跨版本兼容标准范式(推荐放在公共工具模块或脚本顶部) try: # 若在 Python 2 环境中,raw_input 存在,将其重命名为 input input = raw_input except NameError: # 若在 Python 3 环境中,raw_input 不存在会抛出 NameError # 此时无需处理,直接使用 Python 3 原生的 input 即可 pass # 后续业务逻辑中统一使用 input(),在两个版本下均表现为安全返回字符串 username = input("请输入用户名: ") print("输入结果:", username)
原理说明

在 Python 2 中,通过 input = raw_input 语句,用安全的 raw_input 覆盖掉了原有危险的 input;而在 Python 3 中,直接沿用原生的 input。这种写法无需引入第三方库,语法简洁且执行效率极高。

2. 遗留项目迁移排查清单

在将旧工程升级至 Python 3 时,绝不能简单地依赖文本替换,需要依据以下清单逐一排查:

  1. 排查历史代码中的 raw_input(): 这类函数直接转换为 Python 3 的 input() 即可,行为完全等价。使用官方迁移工具 2to3 时,工具会自动将所有 raw_input(...) 重写为 input(...)。
  2. 重点审计历史代码中的 input(): 如果 Python 2 旧代码中调用了 input(),说明原作者可能依赖了其自动转换为整数或列表的副作用。如果直接迁移为 Python 3 的 input(),原本获取到的整数将变成字符串,进而导致后续算术运算抛出 TypeError。
  3. 替换危险的 eval 逻辑: 若旧代码中确实需要输入列表、字典等结构,切勿为了保持兼容而写出 eval(input())。必须统一重构为 ast.literal_eval(input()),从根源上阻断代码注入途径。

总结与开发守则

从 Python 2 的 raw_input() 与 input() 到 Python 3 的唯一定义,这一演进深刻反映了现代编程语言对系统安全与接口一致性的追求。

  • 核心结论:Python 3 的 input() 实质就是 Python 2 的 raw_input(),原 Python 2 input() 的隐式求值机制已被彻底废除。
  • 类型守则:现代 Python 的输入结果永远是纯文本 Unicode 字符串,绝不隐式转换类型。
  • 安全红线:永远不要对未经校验的控制台输入使用 eval();数值转换用 int()/float() 配合异常捕获,结构解析使用 ast.literal_eval()。
相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。