Динамические семантические ошибки в Python

я встретил это как вопрос интервью. Этот вопрос казался интересным. Итак, я размещаю его здесь.

Рассмотрим операцию, которая дает семантическую ошибку, например деление на ноль. По умолчанию компилятор python выводит вывод, например «Invalid Operation» или что-то в этом роде. Можем ли мы контролировать вывод, выдаваемый компилятором Python, например, печатать другое сообщение об ошибке, пропускать это деление на нулевую операцию и выполнять оставшиеся инструкции?
А также, как я могу оценить стоимость семантических проверок времени выполнения? Здесь много экспертов-питонов. Я надеюсь, что кто-то бросит немного света на это. Заранее спасибо.

  • понимание вложенного списка python
  • Индикатор выполнения при загрузке файла через http с запросами
  • Как получить порты, которые прослушивает процесс?
  • Кэширование генератора
  • Почему lil_matrix и dok_matrix настолько медленны по сравнению с обычным dict of dicts?
  • Заменить всю строку в текстовом файле на основе поиска с помощью Python
  • python pandas rank by column
  • От JPG до b64encode до cv2.imread ()
  • 2 Solutions collect form web for “Динамические семантические ошибки в Python”

    Можем ли мы контролировать вывод, выдаваемый компилятором Python, например, печатать другое сообщение об ошибке, пропускать это деление на нулевую операцию и выполнять оставшиеся инструкции?

    Нет, ты не можешь. Вы можете вручную обернуть каждую опасную команду с помощью try...except block, но я предполагаю, что вы говорите об автоматическом восстановлении в определенных строках внутри try...except block или даже полностью автоматически.

    К тому моменту, когда ошибка провалилась, так что sys.excepthook вызывается или независимо от внешней области, если вы поймаете ее раньше, внутренние области исчезнут. Вы можете изменить номера строк с помощью sys.settrace в CPython, хотя это только деталь реализации , но поскольку внешние области исчезли, нет надежного механизма реконверсии.

    Если вы попытаетесь использовать юмористический модуль April's Fools (который использует только что описанный метод), чтобы перепрыгивать блоки даже внутри файла :

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

    вы получите сообщение об ошибке:

     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 

    поэтому я вполне уверен, что это невозможно.


    А также, как я могу оценить стоимость семантических проверок времени выполнения?

    Я не знаю, что это такое, но вы, вероятно, ищете 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() 

    вывод:

     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 

    Таким образом, «семантическая проверка времени выполнения» в этом случае будет занимать 36,4% времени запуска foo .


    Если вы хотите, чтобы определенные блоки вручную были больше, чем вы использовали timeit но меньше, чем вы хотели бы для профилировщика, вместо использования двух time.time() что является довольно неточным методом, я предлагаю Стивену Менеджер контекста секундомера D'Aprano .

    Я бы просто использовал исключение, этот пример использует python 3. Для Python 2 просто удалите аннотации после параметров функции. Таким образом, вы будете использовать подпись подписи -> 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 

    Это пример того, как вы могли поймать Zero Division, создав исключение с помощью ZeroDivisionError .

    Я не буду вдаваться в какие-либо конкретные инструменты для создания журналов, но вы действительно можете понять затраты, связанные с этим проверкой. Вы можете поместить start = time.time() в начале функции и end = time.time() в конце. Если вы понимаете разницу, вы получите время выполнения в секундах.

    Надеюсь, это поможет.

    Python - лучший язык программирования в мире.