Плагин Python Gedit с GTK, ошибка рекурсии во время выполнения фильтра хранилища дерева

#python #plugins #gtk #pygtk #gedit

#python #Плагины #gtk #pygtk #gedit

Вопрос:

У меня проблема с написанием плагина gedit на python с использованием PyGTK.

Основная задача плагина — фильтровать хранилище дерева на основе текста, введенного в текстовой записи. Поиск является «живым» поиском, то есть нет кнопки для нажатия, поиск выполняется по событию ‘key_release_event’, которое обрабатывается методом .refilter() древовидного фильтра:

 widget.connect('key_release_event', self.on_type_search_box_mask)
  

На своей стороне дерево фильтруется функцией:

 treeFilter.set_visible_func(self.search_in_reference, None)
  

Теперь обратите внимание, что дерево довольно большое, у меня 1-2 тысячи строк, но только 1 уровень и всего несколько строк (10-20) имеют дочерние элементы 1 уровня, поэтому максимальная глубина равна двум.

Ну, все работает нормально, когда я что-то печатаю, дерево фильтруется так, как я хочу, даже если я печатаю очень быстро, так что refilter() вызывается дважды в один и тот же момент.

Теперь проблема … если я удаляю текст в текстовом вводе (с помощью пробела или кнопок del), я получаю следующую ошибку python, повторяющуюся много раз:

 Exception RuntimeError: 'maximum recursion depth exceeded while calling a Python object' in <type 'exceptions.RuntimeError'> ignored
Exception RuntimeError: 'maximum recursion depth exceeded while calling a Python object' in <type 'exceptions.RuntimeError'> ignored
Error in sys.excepthook:
RuntimeError: maximum recursion depth exceeded

Original exception was:
RuntimeError: maximum recursion depth exceeded while calling a Python object
  

Ошибка не появляется внезапно с кнопками backspace или del, но после некоторых нажатий (7-15) требуется также меньше нажатий, если я нажимаю эти кнопки быстрее!

После ошибок плагин продолжает работать, но с некоторыми проблемами: строки с дочерними элементами дублируются несколько раз, и функция фильтрации работает плохо…

Теперь вы можете просто сказать мне, что у меня какая-то проблема с рекурсией … но приятная история в том, что у меня нет никакой рекурсии нигде в коде!!! Возможно, какое-то событие вызывается двумя кнопками del и backspace, но я не могу понять, что это такое!

Я действительно схожу с ума!!! пожалуйста, мне нужна помощь!

Luca

Ответ №1:

Хотя у меня нет точного решения вашей проблемы, я мог бы помочь вам сосредоточиться на том, что происходит не так.

Я также наткнулся на «превышена максимальная глубина рекурсии», и, как и в вашем коде, нигде в коде не было рекурсии. Произошло то, что у меня был большой набор очень больших древовидных структур, содержащих некоторые данные. Код также был обработан несколькими способами, чтобы я мог создавать / работать с несколькими деревьями одновременно. Оказалось, что библиотеки python, которые занимаются передачей информации взад и вперед между процессами python, будут рекурсивно упаковывать / распаковывать эту информацию. Итак, когда большое дерево было передано от одного процесса к другому, я нажал «превышена максимальная глубина рекурсии». Несмотря на то, что в моем собственном коде не было рекурсии, когда древовидная структура передавалась между процессами, рекурсивный обход дерева происходил на глубину, превышающую предельную.

Решение моей проблемы заключалось в том, что когда код достиг этой точки обработки этих деревьев, он был вынужден выполняться в одном процессе, что было медленнее, но приемлемо. Также возможно увеличить максимальную глубину рекурсии, но это одно из тех решений, которые «делают на свой страх и риск». Я бы рекомендовал прочитать об этом, прежде чем делать это. Я считаю, что глубина по умолчанию равна 1000, но вы можете настроить ее следующим образом:

 import sys
sys.setrecursionlimit(new_number)
  

Комментарии:

1. большое спасибо, Аврора!! ну, я уже принял во внимание изменение предела рекурсии, но я все еще не пробовал (я был напуган: D). В любом случае, что касается вашей проблемы, она, похоже, отличается от моей, потому что у меня нет дополнительных потоков (но я не знаю, создает ли gtk какие-либо при обработке сигнала) … кстати, используя только один поток в вашем коде, ошибка не возникает? Я думал использовать таймер, чтобы «поиск в реальном времени» не запускался внезапно после каждого нажатия клавиши, но таймер в классе Threading кажется довольно дерьмовым для моей цели…

2. Помните, потоки ! = процессы, и эта проблема возникла у меня с несколькими процессами. Процесс почти как отдельная запущенная программа, в то время как внутри одного процесса может быть много потоков.

3. Ну, я выяснил, в каком случае ошибка occurs…is очень странно для меня: поиск в реальном времени начинается при вводе текстовой записи, и ошибка возникает в функции поиска только тогда, когда я что-то набираю и удаляю все символы, кроме одного, с пробелом… то есть длина запроса = 1 и последнее нажатие клавиши = ‘BackSpace’