我正在阅读一本关于Python的书,它一直在使用代码 eval(input('blah'))
。
我阅读了文档,理解了它,但仍然不知道它如何改变input()
函数。
它是做什么用的?可以有人解释一下吗?
我正在阅读一本关于Python的书,它一直在使用代码 eval(input('blah'))
。
我阅读了文档,理解了它,但仍然不知道它如何改变input()
函数。
它是做什么用的?可以有人解释一下吗?
eval函数允许Python程序在其内部运行Python代码。
示例(eval在交互式shell中使用):
>>> x = 1
>>> eval('x + 1')
2
>>> eval('x')
1
eval()
还可用于执行高度动态的代码,但在使用前应充分了解安全和性能风险。 - George Cumminseval
,也不能通过eval
实现它的功能。 - Mike Grahameval()
函数将一个字符串作为代码来执行。之所以有很多人警告你不要使用它,是因为用户可以将其用作在计算机上运行代码的选项。如果你导入了os
模块并使用eval(input())
,那么一个人可以在input()
中输入os.system('rm -R *')
,这将删除你主目录中的所有文件。(假设你的系统是Unix)。使用eval()
存在安全漏洞。如果需要将字符串转换为其他格式,请尝试使用像int()
这样的函数。
eval
与input()
结合会存在安全漏洞。不要将input()
放在eval
语句中,这样就可以避免问题。 - tim-phillipseval()
还有globals
和locals
关键字参数,可用于限制通过eval
函数可用的函数。例如,如果您加载了一个新的Python解释器,则locals()
和globals()
将是相同的,并且看起来像这样:
>>> globals()
{'__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__doc__': None,
'__spec__': None, '__builtins__': <module 'builtins' (built-in)>,
'__package__': None, '__name__': '__main__'}
在builtins
模块中肯定有一些函数会对系统造成重大破坏。但是我们可以阻止任何我们不想要的东西。比如说,我们想构建一个列表来表示系统上可用核心的域。对于我来说,我有8个核心,所以我想要一个列表[1, 8]
。
>>> from os import cpu_count
>>> eval('[1, cpu_count()]')
[1, 8]
__builtins__
也是可用的。>>> eval('abs(-1)')
1
让我们尝试阻止访问任何全局变量:
>>> eval('[1, cpu_count()]', {'__builtins__':None}, {})
TypeError: 'NoneType' object is not subscriptable
我们已经有效地阻止了所有的__builtins__
函数,从而为我们的系统带来了一定程度的保护。此时,我们可以开始添加我们想要暴露的函数。
>>>from os import cpu_count
>>>exposed_methods = {'cpu_count': cpu_count}
>>>eval('cpu_count()', {'__builtins__':None}, exposed_methods)
8
>>>eval('abs(cpu_count())', {'__builtins__':None}, exposed_methods)
TypeError: 'NoneType' object is not subscriptable
现在我们有了cpu_count
函数,可以阻止我们不想要的一切。在我看来,这是非常强大的,显然从其他答案的范围来看,这不是一个常见的实现。像这样的东西有很多用途,只要处理得当,我个人认为eval
可以安全地用于很大的价值。
N.B.
这些kwargs
的另一个酷炫之处是,您可以开始使用代码的速记。假设您使用eval作为管道的一部分来执行一些导入的文本。文本不需要精确的代码,它可以遵循一些模板文件格式,并且仍然可以执行任何您想要的内容。例如:
>>> from os import cpu_count
>>> eval('[1,cores]', {'__builtins__': None}, {'cores': cpu_count()})
[1, 8]
rm -rf *
):eval("[a for a in ().__class__.__bases__[0].__subclasses__() if 'catch_warnings' in a.__name__][0]()._module.__builtins__['__import__']('os').system('rm -rf *')", {"__builtins__": None})
。 - muddyfisheval
的代码绝对不安全。 - Karl Knechtelinput(...)
等同于eval(raw_input(...))
。在Python 3.x中,raw_input
被重命名为input
,这可能导致了您的困惑(您可能正在查看Python 2.x中input
的文档)。此外,在Python 3.x中,eval(input(...))
将正常工作,但在Python 2中会引发TypeError
。eval
用于将input
返回的字符串强制转换为表达式并进行解释。一般来说,这被认为是不好的做法。input
的意思就像2.x中的raw_input
。 - dan04eval()
,顾名思义,评估传递的参数。
raw_input()
在Python 3.x版本中已更改为input()
。因此,在Python 2.x版本中,eval()
的最常见用法示例是提供与input()
相同的功能。
raw_input将用户输入的数据作为字符串返回,而input则计算输入数据的值并返回该值。
eval(input("bla bla"))
因此复制了Python 2.x中input()
的功能,即评估用户输入的数据。
简而言之:eval()
评估传递给它的参数,因此eval('1 + 1')
返回2。
eval()
的一个有用的应用是从字符串中评估 Python 表达式。例如,从文件加载字典的字符串表示:
running_params = {"Greeting": "Hello, "}
fout = open("params.dat", 'w')
fout.write(repr(running_params))
fout.close()
将其作为变量读取并进行编辑:
fin = open("params.dat", 'r')
diction = eval(fin.read())
diction["Greeting"] += "World!"
fin.close()
print diction
输出:
{'Greeting': 'Hello, World!'}
以下是关于读取一行并解释它的一个可能误导性示例。
尝试使用eval(input())
命令,并输入"1+1"
- 这将打印出2
。Eval用于计算表达式。
eval()
函数将传递的字符串作为 Python 表达式进行评估,并返回结果。例如,eval("1 + 1")
解释并执行表达式 "1 + 1"
并返回结果 (2)。如果你想将评估字符串限制为简单字面值,另一个选项是使用 ast.literal_eval()
。以下是一些示例:
import ast
# print(ast.literal_eval('')) # SyntaxError: unexpected EOF while parsing
# print(ast.literal_eval('a')) # ValueError: malformed node or string
# print(ast.literal_eval('import os')) # SyntaxError: invalid syntax
# print(ast.literal_eval('1+1')) # 2: but only works due to a quirk in parser
# print(ast.literal_eval('1*1')) # ValueError: malformed node or string
print(ast.literal_eval("{'a':1}")) # {'a':1}
ast.literal_eval
不支持运算符,与您的'1+1'
示例相反。尽管如此,它确实支持列表、数字、字符串等,因此是常见eval
用例的良好替代品。 - benjimin+
和-
,因为它们需要支持复数的语法,而且特别处理这个逻辑太难了(或者至少需要额外的工作)。 - Karl Knechtelinput()
函数将返回字符串类型。>>> input('Enter a number: ')
Enter a number: 3
>>> '3'
>>> input('Enter a number: ')
Enter a number: 1+1
'1+1'
eval()
函数将计算返回值(或表达式),该值是一个字符串,并返回整数/浮点数。
>>> eval(input('Enter a number: '))
Enter a number: 1+1
2
>>>
>>> eval(input('Enter a number: '))
Enter a number: 3.14
3.14
然而,在这里最好使用更具体的工具,例如int()
或float()
。
>>> float(input('Enter a number: '))
Enter a number: 3.14
3.14