Python UNO и потоки

Я работаю с Python UNO, используя «внутреннюю» (Libreoffice — хост-процесс) версию, в которой интерпретатор Python находится внутри Libreoffice/Openoffice. Я хотел бы сделать код неблокирующим... то есть, как только код вызывается как макрос, он запускает второй поток и возвращает основной поток обратно в Office, чтобы он не блокировал пользовательский интерфейс, пока он продолжает работать очень длительный процесс (10-20 минут времени исполнения).

Когда я попробовал именно это, LibreOffice зависает навсегда. Я искал почти везде, но, кроме странной ссылки на импорт scipy во второй поток, а затем блокировку во время ожидания в этом потоке (myrhread.join()), похоже, нигде это не делается.

В качестве альтернативы можно ли создать новый ServiceManager, чтобы я мог вызвать второй процесс, а затем связать его с ServiceManager, чтобы я мог вернуться в LibreOffice обычным способом, не блокируя его «призрачным потоком»?


person Paul Campbell    schedule 03.03.2016    source источник
comment
Привет и добро пожаловать в StackOverflow! Пожалуйста, опубликуйте упрощенную версию кода, который вы пробовали до сих пор, тот, который зависает. Пара вопросов: код PyUNO вызывается как макрос (например, Tools -> Macros -> Run Macro) или извне с использованием прослушивающего экземпляра? Кроме того, что делает этот длительный процесс — изменяет ли он документ Writer или делает что-то внешнее, например, создает файл где-то еще в операционной системе?   -  person Jim K    schedule 03.03.2016
comment
Как указано выше, он вызывается как макрос (живет внутри процесса LibreOffice). Если бы он был снаружи, то резьба была бы не нужна. Причина того, что код работает медленно, заключается в том, что после экспериментов я обнаружил, что создание аннотации происходит довольно медленно. Мне нужно вставить что-то вроде 1500 аннотаций ячеек. Без аннотаций он выполняется за секунды.   -  person Paul Campbell    schedule 07.03.2016


Ответы (1)


После долгих копаний я нашел ответ здесь:

Пример создания потоков в LibreOfficeForum

Для простых длительных задач, где в противном случае блокировался бы поток пользовательского интерфейса, это работает очень хорошо. Соответствующий код выглядит следующим образом:

from threading import Thread
from time import sleep
import uno

t = None

def test_worker(doc):

    # Wait 30 seconds for demonstration purposes
    sleep(30)

    # Get the 1st sheet in the document and insert text into cell A1
    doc.Sheets.getByIndex(0).getCellByPosition(0,0).String = "I'm back"

def delayedRun(*args):
    global t
    doc = XSCRIPTCONTEXT.getDocument()
    t = Thread(target = test_worker, args = (doc,))
    t.start()

g_exportedScript = delayedRun,
person Paul Campbell    schedule 07.03.2016
comment
Это хороший ответ. Я был бы рад помочь, но мне нужно было больше информации. В следующий раз после того, как зададите вопрос, пожалуйста, периодически проверяйте его, чтобы ответить на любые комментарии. - person Jim K; 08.03.2016
comment
Для других, которые находят этот ответ, global t и t = None считаются плохим кодом Python и также не нужны в этом примере. Поэтому удалите эти строки, прежде чем адаптироваться к проекту. - person Jim K; 20.05.2021