time.sleep, который позволяет родительскому приложению все еще оценивать?
В последнее время я сталкивался с ситуациями при написании скриптов для Maya и Houdini, где мне нужно подождать, пока обновятся некоторые аспекты GUI, прежде чем я смогу вызвать остальную часть моего кода Python. Я думал, что вызов time.sleep в обеих ситуациях решил бы мою проблему, но кажется, что time.sleep также поддерживает родительское приложение. Это означает, что мой сценарий оценивает одно и то же независимо от того, находится ли там сон, он просто останавливается на полпути.
У меня есть мысль запустить свой скрипт в отдельном потоке в Python, чтобы посмотреть, освободит ли это приложение, которое еще будет работать во время сна, но у меня еще не было времени проверить это.
Подумал, что я хотел бы спросить, если кто-нибудь знает какое-то другое решение этого сценария.
2 ответа
Maya - точнее, Maya Python - на самом деле не многопоточный (сам Python имеет хитрый вид многопоточности, потому что все потоки борются за ужасную глобальную блокировку интерпретатора, но это не ваша проблема здесь). Вы можете просто запустить многопоточный код в Maya, используя модуль потоков; пытаться:
import time
import threading
def test():
for n in range (0, 10):
print "hello"
time.sleep(1)
t = threading.Thread(target = test)
t.start()
Это напечатает "привет" вашему слушателю 10 раз с интервалом в одну секунду, не отключая интерактивность.
К сожалению, многие части Maya, включая, в частности, ВСЕ пользовательский интерфейс, созданный пользователем, и большинство видов манипулирования сценами, могут быть запущены только из "основного" потока - того, который владеет пользовательским интерфейсом Maya. Таким образом, вы не можете сделать скрипт для изменения содержимого текстового поля в окне, используя описанную выше технику (что еще хуже, вы получите вводящие в заблуждение сообщения об ошибках - код, который работает, когда вы запускаете его из прослушивателя, но ошибки, когда Вы вызываете его из потока и вежливо возвращаете совершенно неправильные коды ошибок). Вы можете делать такие вещи, как сетевое взаимодействие, запись в файл или длинные вычисления в отдельном потоке, без проблем, но пользовательский интерфейс работает, и многие обычные задачи сцены не будут выполнены, если вы попытаетесь выполнить их из потока.
В Maya есть частичный обходной путь для этого в модуле maya.utils. Вы можете использовать функции executeDeferred и executeInMainThreadWithResult. Они будут ждать простоя для запуска (что означает, например, что они не будут работать, если вы воспроизводите анимацию), а затем запускаются, как если бы вы делали это в главном потоке. Пример из документов Maya дает идею:
import maya.utils import maya.cmds
def doSphere( radius ):
maya.cmds.sphere( radius=radius )
maya.utils.executeInMainThreadWithResult( doSphere, 5.0 )
Это дает вам большую часть того, что вы хотите, но вам нужно тщательно подумать о том, как разбить вашу задачу на потоки-дружественные куски. И, конечно же, запуск многопоточных программ всегда сложнее, чем однопоточная альтернатива, вам нужно спроектировать код так, чтобы все не сломалось, если другой поток портится с переменной во время работы. Хорошее параллельное программирование - это большой котелок рыбы, хотя сводится к паре основных идей:
1) установить исключительный контроль над объектами (для коротких операций), используя RLocks, когда это необходимо, 2) поместить общие данные в безопасные контейнеры, как в Queue в примере @dylan, 3) четко понимать, какие объекты являются общими (их должно быть немного!), А какие не
Вот достойный (длинный) обзор.
Что касается Гудини, я точно не знаю, но эта статья звучит так, как будто там возникают подобные проблемы.
Лучшее решение, а не сон, - это цикл времени. Настройте цикл while для проверки общего значения (или даже многопоточной структуры, такой как очередь). Родительские процессы, на которых вы ожидаете, могут выполнять свою работу (или дочерние процессы, не важно, кто что порождает), и когда они заканчивают свою работу, они отправляют true/false/0/1/ что угодно в переменную Queue/, позволяя другим процессам знаю, что они могут продолжаться.