Python Language
Utförande av dynamisk kod med "exec" och "eval"
Sök…
Syntax
- eval (uttryck [, globaler = Inget [, lokalbefolkningen = Inget]])
- exec (objekt)
- exec (objekt, globaler)
- exec (objekt, globaler, lokalbefolkningen)
parametrar
Argument | detaljer |
---|---|
expression | Uttrycket koden som en sträng, eller en code -objekt |
object | Uttalandet kod som en sträng, eller en code objekt |
globals | Ordboken som ska användas för globala variabler. Om lokalbefolkningen inte anges används den också för lokalbefolkningen. Om de utelämnas används de globals() av samtalsomfånget. |
locals | Ett mappningsobjekt som används för lokala variabler. Om den utelämnas används den som skickas för globals istället. Om båda utelämnas används globals() och locals() i samtalsområdet för globals respektive locals . |
Anmärkningar
I exec
, om globals
är locals
(dvs. de hänvisar till samma objekt), körs koden som om den är på modulnivå. Om globals
och locals
är distinkta objekt körs koden som om den var i en klasskropp .
Om globals
skickas in, men inte anger __builtins__
tangenten, __builtins__
Python inbyggda funktioner och namn automatiskt till det globala omfånget. För att undertrycka tillgängligheten för funktioner som print
eller isinstance
i det exekverade omfånget, låt globals
ha nyckeln __builtins__
mappad till värdet None
. Detta är dock inte en säkerhetsfunktion.
Python 2-specifik syntax bör inte användas; Python 3-syntaxen fungerar i Python 2. Följaktligen avskrivs följande former: <s>
-
exec object
-
exec object in globals
-
exec object in globals, locals
Utvärdera uttalanden med exec
>>> code = """for i in range(5):\n print('Hello world!')"""
>>> exec(code)
Hello world!
Hello world!
Hello world!
Hello world!
Hello world!
Utvärdera ett uttryck med eval
>>> expression = '5 + 3 * a'
>>> a = 5
>>> result = eval(expression)
>>> result
20
Förkompilera ett uttryck för att utvärdera det flera gånger
compile
inbyggd funktion kan användas för att kompilera ett uttryck till ett kodobjekt; detta kodobjekt kan sedan överföras till eval. Detta påskyndar de upprepade körningarna av den utvärderade koden. Den tredje parametern som ska compile
måste vara strängen 'eval'
.
>>> code = compile('a * b + c', '<string>', 'eval')
>>> code
<code object <module> at 0x7f0e51a58830, file "<string>", line 1>
>>> a, b, c = 1, 2, 3
>>> eval(code)
5
Utvärdera ett uttryck med eval med hjälp av anpassade globaler
>>> variables = {'a': 6, 'b': 7}
>>> eval('a * b', globals=variables)
42
Som ett plus kan koden inte av misstag hänvisa till namnen definierade utanför:
>>> eval('variables')
{'a': 6, 'b': 7}
>>> eval('variables', globals=variables)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1, in <module>
NameError: name 'variables' is not defined
defaultdict
använder defaultdict
kan till exempel ha odefinierade variabler inställda på noll:
>>> from collections import defaultdict
>>> variables = defaultdict(int, {'a': 42})
>>> eval('a * c', globals=variables) # note that 'c' is not explicitly defined
0
Utvärdering av en sträng som innehåller en Python-bokstav med ast.literal_eval
Om du har en sträng som innehåller Python-bokstäver, till exempel strängar, flottörer osv, kan du använda ast.literal_eval
att utvärdera dess värde istället för eval
. Detta har den tillagda funktionen att endast tillåta vissa syntax.
>>> import ast
>>> code = """(1, 2, {'foo': 'bar'})"""
>>> object = ast.literal_eval(code)
>>> object
(1, 2, {'foo': 'bar'})
>>> type(object)
<class 'tuple'>
Detta är dock inte säkert för exekvering av kod som tillhandahålls av otillförlitlig användare, och det är trivialt att krascha en tolk med noggrant utformad inmatning
>>> import ast
>>> ast.literal_eval('()' * 1000000)
[5] 21358 segmentation fault (core dumped) python3
Här är ingången en sträng av ()
upprepad en miljon gånger, vilket orsakar en krasch i CPython-parser. CPython-utvecklare anser inte buggar i parser som säkerhetsproblem.
Utför kod som tillhandahålls av en betrodd användare som använder exec, eval eller ast.literal_eval
Det är inte möjligt att använda eval
eller exec
att säkert köra kod från otillförlitlig användare. Till och med ast.literal_eval
är benägen att kraschar i tolkaren. Det är ibland möjligt att skydda mot exekvering av skadlig kod, men det utesluter inte möjligheten till direkt kraschar i parser eller tokenizer.
För att utvärdera kod av en opålitlig användare måste du gå till någon modul från tredje part, eller kanske skriva din egen parser och din egen virtuella maskin i Python.