Ricerca…


Sintassi

  • eval (espressione [, globals = None [, locals = None]])
  • exec (oggetto)
  • exec (oggetto, globals)
  • exec (oggetto, globals, gente del posto)

Parametri

Discussione Dettagli
expression Il codice dell'espressione come una stringa o un oggetto code
object Il codice dell'istruzione come una stringa o un oggetto code
globals Il dizionario da usare per le variabili globali. Se la gente del posto non è specificata, questo è anche usato per i locali. Se omesso, vengono utilizzati i globals() dell'ambito di chiamata.
locals Un oggetto di mappatura che viene utilizzato per le variabili locali. Se omesso, viene utilizzato invece quello per le globals . Se entrambi vengono omessi, i globals() e i locals() dell'ambito chiamante vengono utilizzati rispettivamente per globals e locals .

Osservazioni

In exec , se i globals sono locals (cioè si riferiscono allo stesso oggetto), il codice viene eseguito come se fosse a livello di modulo. Se globals e locals sono oggetti distinti, il codice viene eseguito come se fosse in un corpo di classe .

Se l'oggetto globals viene passato, ma non specifica la chiave __builtins__ , le funzioni e i nomi incorporati di Python vengono automaticamente aggiunti all'ambito globale. Per sopprimere la disponibilità di funzioni come print o isinstance nell'ambito eseguito, lasciare che le globals abbiano la chiave __builtins__ mappata sul valore None . Tuttavia, questa non è una funzione di sicurezza.

La sintassi specifica di Python 2 non dovrebbe essere utilizzata; la sintassi Python 3 funzionerà in Python 2. Quindi i seguenti moduli sono deprecati: <s>

  • exec object
  • exec object in globals
  • exec object in globals, locals

Valutazione di dichiarazioni con exec

>>> code = """for i in range(5):\n    print('Hello world!')"""
>>> exec(code)
Hello world!
Hello world!
Hello world!
Hello world!
Hello world!

Valutare un'espressione con eval

>>> expression = '5 + 3 * a'
>>> a = 5
>>> result = eval(expression)
>>> result
20

Precompilare un'espressione per valutarla più volte

compile funzione incorporata può essere utilizzata per precompilare un'espressione a un oggetto codice; questo oggetto codice può quindi essere passato a valutazione. Ciò velocizzerà le ripetute esecuzioni del codice valutato. Il terzo parametro da compile deve essere la stringa '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

Valutare un'espressione con eval utilizzando globals personalizzati

>>> variables = {'a': 6, 'b': 7}
>>> eval('a * b', globals=variables)
42

Come un vantaggio, con questo il codice non può accidentalmente fare riferimento ai nomi definiti al di fuori:

>>> 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

L'uso di defaultdict consente ad esempio di avere variabili non definite impostate su zero:

>>> from collections import defaultdict
>>> variables = defaultdict(int, {'a': 42})
>>> eval('a * c', globals=variables)  # note that 'c' is not explicitly defined
0

Valutare una stringa contenente un letterale Python con ast.literal_eval

Se hai una stringa che contiene letterali Python, come stringhe, float ecc., Puoi usare ast.literal_eval per valutare il suo valore invece di eval . Questo ha la caratteristica aggiunta di consentire solo una certa sintassi.

>>> import ast
>>> code = """(1, 2, {'foo': 'bar'})"""
>>> object = ast.literal_eval(code)
>>> object
(1, 2, {'foo': 'bar'})
>>> type(object)
<class 'tuple'>

Tuttavia, questo non è sicuro per l'esecuzione del codice fornito da un utente non fidato, ed è banale arrestare un interprete con un input accuratamente predisposto

>>> import ast
>>> ast.literal_eval('()' * 1000000)
[5]    21358 segmentation fault (core dumped)  python3

Qui, l'input è una stringa di () ripetuta un milione di volte, che provoca un crash nel parser CPython. Gli sviluppatori CPython non considerano i bug nel parser come problemi di sicurezza.

Esecuzione del codice fornito dall'utente non fidato mediante exec, eval o ast.literal_eval

Non è possibile utilizzare eval o exec per eseguire il codice dell'utente inaffidabile. Anche ast.literal_eval è soggetto a crash nel parser. A volte è possibile evitare l'esecuzione di codice dannoso, ma non esclude la possibilità di arresto anomalo nel parser o nel tokenizer.

Per valutare il codice da un utente non fidato è necessario passare a qualche modulo di terze parti, o magari scrivere il proprio parser e la propria macchina virtuale in Python.



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow