Python中的input和raw_input哪个更实用?

32
我目前教授大一的大学生Python,惊讶地发现看似无害的input函数,有些学生决定使用它(并对奇怪的行为感到困惑),实际上隐藏着一个eval调用。

那么我的问题是,为什么input函数会调用eval,这有什么用处,而不使用raw_input更安全呢?我知道这在Python 3中已经改变了,但这似乎是一个不寻常的设计决策。

Python 2.x输入函数文档


8
对于代码竞赛很有用。 - John La Rooy
回答“为什么”的问题 - Python的第一个REPL可能是while 1: print input()。我敢打赌,在那个古老的时代,支持良好的编程实践并不是Python优先考虑的事情,就像现在这样。Python 3的while True: print(eval(input()))甚至可能更加令人困惑 - 所有这些嵌套的括号! - Petr Viktorin
4个回答

38

在使用Python时,是否有必要使用Python 2的input()功能而不是raw_input()?

没有。


input()会评估用户输入的代码。它将Python的全部能力交给了用户。使用生成器表达式/列表推导式,__import__if/else运算符,任何Python可以做到的事情都可以用一个表达式实现。恶意用户可以使用input()删除文件(__import__('os').remove('precious_file')),monkeypatch程序的其余部分(setattr(__import__('__main__'), 'function', lambda:42)),等等。

普通用户不需要使用所有高级功能。如果不需要表达式,请使用ast.literal_eval(raw_input()) - literal_eval函数是安全的。

如果你正在为高级用户编写代码,请给他们更好的输入代码的方式。插件、用户模块等——拥有完整的Python语法,而不仅仅是功能。

如果你绝对确定自己知道在做什么,请使用eval(raw_input())。对于有经验的人来说,eval会让他们察觉到“我很危险!”但是,你可能永远不需要这个功能。


input()是Python 3正在解决的旧设计错误之一。


这就是我所想的,即使你需要 input 的功能,如果你使用 eval(raw_input()),那么你至少会意识到它是危险的。而且除此之外,没有真正好的理由去使用它。谢谢! - luketparkinson

7

Python的Input函数返回一个对象,该对象是表达式求值的结果。raw_input函数返回一个字符串。

name = "Arthur"
age = 45

first = raw_input("Please enter your age ")
second = input("Please enter your age again ")

# first will always contain a string

# second could contain any object and you can even
# type in a calculation and use "name" and "age" as
# you enter it at run time ...

print "You said you are",first
print "Then you said you are",second

以下是运行示例:
示例1
Prompt$ python yraw 
Please enter your age 45 
Please enter your age again 45 
You said you are 45 Then you said you are 45

示例:2
Prompt$ python yraw
Please enter your age 45 + 7
Please enter your age again 45 + 7
You said you are 45 + 7 Then you said you are 52 
Prompt$

问:为什么input函数会调用eval函数?

答:考虑这样一种情况,用户在input函数中输入一个表达式'45 + 7',与Python 2.x中的raw_input相比,input函数将给出正确的结果。


1
或者他们可以输入 quit(),但如果您正在执行关键代码部分,则相当危险... - tobyodavies
8
或者他们可以输入__import__('os').remove('precious_file'),这在任何地方都是相当危险的。在几乎所有情况下,ast.literal_eval(raw_input())是更好的选择。难怪Python 3的input()的工作方式类似于Python 2的raw_input() - Petr Viktorin
7
我不同意这个答案。为什么您认为输入的“正确结果”是52?我认为正确的结果应该是“请输入一个数字”。一个要求用户输入数字的程序没有充分的理由去计算用户可能提供的Python表达式的结果。这不仅是荒谬的行为,而且正如Petr所指出的那样,也是一个严重的安全风险。问题是“输入是否有用”,答案是“否”。 - mgiuca
这并没有什么帮助,如果你想构建一个计算器,那么最好通过解析器来安全地实现,例如在这里描述的方式 https://dev59.com/nHE95IYBdhLWcg3wSsCD#9558001。 - Chris_Rands

4

input 函数在交互式 Python shell 中作为构建块非常有用。你肯定是对它的工作方式感到惊讶,而且它过于特定于某个目的,因此被认为不适合作为内置函数 - 这也是我认为它在 Python 3 中被删除的原因。


2

raw_input 更好,它始终返回用户输入的内容而不进行任何更改。 相反,input() 函数会尝试将您输入的内容转换为 Python 代码,并且它存在安全问题,因此应避免使用。

在实际程序中不要使用 input(),请使用能够处理特定输入格式的解析器来解析输入,而不是通过评估输入作为 Python 代码来解析。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接