Dynamic semantic errors in Python

I came across this as an interview question. This question seemed interesting. So, I post it here.

Consider an operation that gives a semantic error, for example division by zero. By default, the python compiler outputs output like "Invalid Operation" or something like that. Can we control the output produced by the Python compiler, for example, print some other error message, skip this division by the zero operation, and execute the remaining instructions?
And also, how can I estimate the cost of semantic runtime checks? There are many python experts here. I hope someone throws some light on this. Thanks in advance.

+1
source share
2 answers

Can we control the output generated by the Python compiler, for example, print another error message, skip this division by the zero operation, and follow the remaining instructions?

No, you can’t. You can manually wrap each dangerous command with a try...except block, but I assume that you are talking about automatic recovery for certain lines in a try...except block, or even completely automatically.

By the time the error has failed, so sys.excepthook is called or some other appearance, if you catch it earlier, the inner areas have disappeared. You can change the sys.settrace line sys.settrace in CPython, although this is only an implementation detail , but since the outer areas are gone there is no reliable mechanism of recurrence.

If you try to use the goto April fools humorous module (which uses the method just described) to jump blocks even inside the file:

 from goto import goto, label try: 1 / 0 label .foo print("recovered") except: goto .foo 

You will receive an error message:

 Traceback (most recent call last): File "rcv.py", line 9, in <module> goto .foo File "rcv.py", line 9, in <module> goto .foo File "/home/joshua/src/goto-1.0/goto.py", line 272, in _trace frame.f_lineno = targetLine ValueError: can't jump into the middle of a block 

therefore, I am sure that this is not possible.


And also, how can I estimate the cost of semantic runtime checks?

I don't know what it is, but you are probably looking for line_profiler :

 import random from line_profiler import LineProfiler profiler = LineProfiler() def profile(function): profiler.add_function(function) return function @profile def foo(a, b, c): if not isinstance(a, int): raise TypeError("Is this what you mean by a 'run-time semantic check'?") d = b * c d /= a return d**a profiler.enable() for _ in range(10000): try: foo(random.choice([2, 4, 2, 5, 2, 3, "dsd"]), 4, 2) except TypeError: pass profiler.print_stats() 

output:

 Timer unit: 1e-06 s File: rcv.py Function: foo at line 11 Total time: 0.095197 s Line # Hits Time Per Hit % Time Line Contents ============================================================== 11 @profile 12 def foo(a, b, c): 13 10000 29767 3.0 31.3 if not isinstance(a, int): 14 1361 4891 3.6 5.1 raise TypeError("Is this what you mean by a 'run-time semantic check'?") 15 16 8639 20192 2.3 21.2 d = b * c 17 8639 20351 2.4 21.4 d /= a 18 19 8639 19996 2.3 21.0 return d**a 

Thus, the β€œsemantic check of runtime" in this case will occupy 36.4% of the time foo works.


If you want certain blocks manually to be larger than you would use timeit , but smaller than you would like for the profiler, instead of using two calls to time.time() (which is pretty inaccurate) I suggest Stephen D'Apano Stopwatch Context Manager .

+6
source

I would just use an exception, this example uses python 3. For Python 2, just remove the annotations after the function parameters. So your signature will look like this:> f(a,b) :

 def f(a: int, b: int): """ @param a: @param b: """ try: c = a / b print(c) except ZeroDivisionError: print("You idiot, you can't do that ! :P") if __name__ == '__main__': f(1, 0) 

 >>> from cheese import f >>> f(0, 0) You idiot, you can't do that ! :P >>> f(0, 1) 0.0 >>> f(1, 0) You idiot, you can't do that ! :P >>> f(1, 1) 1.0 

This is an example of how you could catch Zero Division by ZeroDivisionError exception with ZeroDivisionError .

I will not go into any special tools for creating journals, but you can really understand the costs associated with this type of verification. You can put start = time.time() at the beginning of the function and end = time.time() at the end. If you notice the difference, you will get the lead time in seconds.

I hope this helps.

+1
source

Source: https://habr.com/ru/post/975880/


All Articles