Как получить доступ к DOM в потоке или подпроцессе Python

1

Я пытаюсь обновить epub-ридер, чтобы иметь дело с медиа-оверлеями. Есть две вещи, которые нужно сделать: воспроизвести звук наложения и одновременно выделить текст, который будет читаться. Воспроизведение звука было непростым. Я использовал модуль pydub для измельчения файлов mp3 или mp4 и воспроизводил их последовательно. Для отображения содержимого epub я использую WebKit.Webview из gi.repository. Это дает доступ к документу DOM и позволяет возиться с элементами, которые он содержит. В качестве альтернативы я могу добиться такого же эффекта, используя Javascript.

Но, хотя это работает в основном потоке выполнения, оно не происходит в другом потоке или даже в другом процессе, если я вилка из основного процесса. Чтобы проиллюстрировать проблему, я попробовал это:

from multiprocessing import Process

def on_access_dom(self, widget, data=None):
    if __name__ == '__main__':
        p = Process(target=self.jsdom)
        p.start()
        p.join()
    #self.jsdom()


def jsdom(self):
    cmd = '''node = document.getElementById("f003");
       node.innerHTML="<span style='color: red'>red text</span>"; '''
    self.viewer.execute_script(cmd)

Идея состоит в том, чтобы показать текст красным цветом. Я позже использовал бы цвет, указанный в css для epub. Выше я использую javascript. В качестве альтернативы я могу заменить функцию jsdom на

def trydom(self):
    dom = self.domdoc
    text_id = 'f003'
    node = dom.get_element_by_id(text_id)
    text = node.get_outer_html()
    angle = text.find('>')
    start = text[:angle]+' style="color: red">'
    text = text[angle+1:]
    node.set_outer_html(start+text)

Теперь, если вместо запуска нового процесса или нового потока, я запускаю jsdom или trydom непосредственно в основном потоке. все работает по своему желанию. Но в новой нити или процессе ничего не происходит.

Я что-то пропустил? Я не вижу, как GIL может быть виновником, поскольку он должен применяться к потокам, но не к разветвленным процессам.

Любая помощь с благодарностью получила.

Теги:
multithreading

1 ответ

0

Ответ был найден по адресу https://wiki.gnome.org/Projects/PyGObject/Threading

Моя функция trydom не изменилась. Однако on_access_dom теперь выглядит

def on_access_dom(self, widget, data=None):
    red = threading.Thread(target=self.wrap_trydom, daemon=True)
    red.start()

вместе с

def wrap_trydom(self):
    GLib.idle_add(self.trydom)

Моя проблема заключалась в том, что я не узнал, что Gtk вам не нравится, когда вы обращаетесь к пользовательскому интерфейсу напрямую из потоков, которые не соответствуют циклу основного события. Функция idle_add позволяет сделать это, выполнив код, пока цикл основного события не работает.

Надеюсь, этот ответ полезен для других людей. Он позволил мне продолжить мою основную задачу по разработке устройства для чтения epub, которое поддерживает медиа-оверлеи.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню