File: basics.rst

package info (click to toggle)
python-asteval 1.0.6-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 296 kB
  • sloc: python: 2,606; makefile: 53
file content (191 lines) | stat: -rw-r--r-- 6,482 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
================
Using Asteval
================

This chapter gives a quick overview of asteval, showing basic usage and the
most important features.  Further details can be found in the next chapter
(:ref:`asteval_api`).


Creating and using an asteval Interpreter
=============================================

The asteval module is very easy to use.  Import the module and create an Interpreter:

    >>> from asteval import Interpreter
    >>> aeval = Interpreter()

and now you have an embedded interpreter for a procedural, mathematical language
that is very much like python::

    >>> aeval('x = sqrt(3)')
    >>> aeval('print(x)')
    1.73205080757
    >>> aeval('''
    for i in range(10):
        print(i, sqrt(i), log(1+1))
    ''')
    0 0.0 0.0
    1 1.0 0.69314718056
    2 1.41421356237 1.09861228867
    3 1.73205080757 1.38629436112
    4 2.0 1.60943791243
    5 2.2360679775 1.79175946923
    6 2.44948974278 1.94591014906
    7 2.64575131106 2.07944154168
    8 2.82842712475 2.19722457734
    9 3.0 2.30258509299

There are lots of options when creating the Interpreter to controller what
functionality is and isn't allowed and to pre-load data and functions.  The
default interpreter gives a limited but useful version of the Python language.


accessing the symbol table
=============================

The symbol table (that is, the mapping between variable and function names and
the underlying objects) is a simple dictionary (by default, see
:ref:`symtable_section` for details of an optional alternative) held in the
:attr:`symtable` attribute of the interpreter, and can be read or written to::

    >>> aeval('x = sqrt(3)')
    >>> aeval.symtable['x']
    1.73205080757
    >>> aeval.symtable['y'] = 100
    >>> aeval('print(y/8)')
    12.5

Note here the use of true division even though the operands are integers.

As with Python itself, valid symbol names must match the basic regular
expression pattern::

   valid_name = [a-zA-Z_][a-zA-Z0-9_]*

In addition, certain names are reserved in Python, and cannot be used
within the asteval interpreter.  These reserved words are:

    and, as, assert, async, await, break, class, continue, def, del, elif,
    else, eval, except, exec, execfile, finally, for, from, global, if, import,
    in, is, lambda, nonlocal, not, or, pass, print, raise, return, try, while,
    with, True, False, None, __import__, __package__



built-in functions
=======================

At startup, many symbols are loaded into the symbol table from Python's
builtins and the ``math`` module.  The builtins include several basic Python
functions:

    abs, all, any, bin, bool, bytearray, bytes, chr, complex,
    dict, dir, divmod, enumerate, filter, float, format,
    frozenset, hash, hex, id, int, isinstance, len, list, map,
    max, min, oct, ord, pow, range, repr, reversed, round,
    set, slice, sorted, str, sum, tuple, zip

and a large number of named exceptions:

    ArithmeticError, AssertionError, AttributeError,
    BaseException, BufferError, BytesWarning, DeprecationWarning,
    EOFError, EnvironmentError, Exception, False,
    FloatingPointError, GeneratorExit, IOError, ImportError,
    ImportWarning, IndentationError, IndexError, KeyError,
    KeyboardInterrupt, LookupError, MemoryError, NameError, None,
    NotImplemented, NotImplementedError, OSError, OverflowError,
    ReferenceError, RuntimeError, RuntimeWarning, StopIteration,
    SyntaxError, SyntaxWarning, SystemError, SystemExit, True,
    TypeError, UnboundLocalError, UnicodeDecodeError,
    UnicodeEncodeError, UnicodeError, UnicodeTranslateError,
    UnicodeWarning, ValueError, Warning, ZeroDivisionError


The symbols imported from Python's ``math`` module include:

    acos, acosh, asin, asinh, atan, atan2, atanh, ceil, copysign,
    cos, cosh, degrees, e, exp, fabs, factorial, floor, fmod,
    frexp, fsum, hypot, isinf, isnan, ldexp, log, log10, log1p,
    modf, pi, pow, radians, sin, sinh, sqrt, tan, tanh, trunc

.. _numpy: https://numpy.org/

If available, about 300 additional symbols are imported from `numpy`_.

conditionals and loops
==========================

If-then-else blocks, for-loops (including the optional ``else`` block),
``while`` loops (also including optional ``else`` block), and ``with`` blocks
are supported, and work exactly as they do in python.  Thus:

    >>> code = """
    sum = 0
    for i in range(10):
        sum += i*sqrt(*1.0)
        if i % 4 == 0:
            sum = sum + 1
    print("sum = ", sum)
    """
    >>> aeval(code)
    sum =  114.049534067

comprehensions
================

list, dict, and set comprehension are supported, acting just as they do in
Python.  Generators, yield, and async programming are not currently supported.


printing
===============

For printing, asteval emulates Python's native :func:`print` function.  You
can change where output is sent with the ``writer`` argument when creating
the interpreter, or suppress printing all together with the ``no_print``
option.  By default, outputs are sent to :py:data:`sys.stdout`.


writing functions
===================

User-defined functions can be written and executed, as in python with a
``def`` block, for example::

   >>> from asteval import Interpreter
   >>> aeval = Interpreter()
   >>> code = """def func(a, b, norm=1.0):
   ...     return (a + b)/norm
   ... """
   >>> aeval(code)
   >>> aeval("func(1, 3, norm=10.0)")
   0.4


exceptions
===============

Asteval monitors and caches exceptions in the evaluated code.  Brief error
messages are printed (with Python's print function, and so using standard
output by default), and the full set of exceptions is kept in the
:attr:`error` attribute of the :class:`Interpreter` instance.  This
:attr:`error` attribute is a list of instances of the asteval
:class:`ExceptionHolder` class, which is accessed through the
:meth:`get_error` method.  The :attr:`error` attribute is reset to an empty
list at the beginning of each :meth:`eval`, so that errors are from only
the most recent :meth:`eval`.

Thus, to handle and re-raise exceptions from your Python code in a simple
REPL loop, you'd want to do something similar to

   >>> from asteval import Interpreter
   >>> aeval = Interpreter()
   >>> while True:
   >>>     inp_string = raw_input('dsl:>')
   >>>     result = aeval(inp_string)
   >>>     if len(aeval.error)>0:
   >>>         for err in aeval.error:
   >>>             print(err.get_error())
   >>>     else:
   >>>         print(result)