общение с долгосрочными задачами в python - PullRequest
1 голос
/ 31 марта 2009

У меня есть приложение с графическим интерфейсом Python, которое использует долго выполняющуюся функцию из .so / .dll, которую она вызывает через ctypes.

Я ищу способ связи с функцией, когда она выполняется в отдельном потоке или процессе, чтобы я мог запросить ее преждевременное завершение (что требует некоторой работы на стороне C перед возвратом частичного результата). Я полагаю, что для этого потребуется какой-то сигнал или чтение сигналов из каналов, но я хочу сделать его как можно более простым.

Что вы считаете лучшим подходом для решения такого рода проблем? Я могу изменить код как на стороне Python, так и на стороне C.

Ответы [ 4 ]

2 голосов
/ 31 марта 2009

Вы упоминаете, что можете изменить обе стороны C и Python. Чтобы избежать написания каких-либо сокетов или сигнального кода на C, проще всего разбить большую функцию C на 3 меньших отдельных функции, которые выполняют настройку, небольшой пакет работ и очистку. Рабочий пакет должен составлять от 1 мс до 1 секунды, чтобы достичь баланса между отзывчивостью и низкими издержками. Может быть сложно разбить вычисления на такие куски, несмотря на изменение размеров данных, но у вас будет такая же проблема в одной большой функции, которая также выполняет ввод / вывод.

Напишите рабочий процесс на Python, который вызывает эти 3 функции через ctypes. Пусть рабочий процесс проверит объект Queue на наличие сообщения от графического интерфейса пользователя, чтобы остановить вычисление на ранней стадии. Убедитесь, что вы используете неблокирующий вызов Queue.get_nowait вместо Queue.get. Если рабочий процесс находит сообщение о досрочном выходе, вызовите код очистки C и верните частичный результат.

2 голосов
/ 31 марта 2009

Здесь вам нужно ответить на две части: одна - как обмениваться данными между двумя процессами (ваш графический интерфейс и процесс, выполняющий функцию), а другая - как изменить вашу функцию, чтобы она отвечала на асинхронные запросы ( «о, мне сказали просто вернуть все, что у меня есть»).

Разработка ответа на второй вопрос, вероятно, продиктует ответ на первый. Вы можете сделать это с помощью сигналов (в этом случае вы получите обработчик сигнала, который получает контроль над процессом, может искать более подробные инструкции в другом месте и изменить свои внутренние структуры данных, прежде чем вернуть управление своей функции), или у вас может быть ваша функция отслеживать интерфейс управления для команд (каждую миллисекунду проверять, есть ли ожидающая команда, и если есть, посмотреть, что это такое).

В первом случае вам понадобится обработка сигналов ANSI C (signal (), sighandler_t), во втором - канал или аналогичный (pipe () и select ()).

0 голосов
/ 31 марта 2009

Вы сказали это: сигналы и трубы.

Это не должно быть слишком сложным, но будет гораздо проще, если вы используете существующую структуру, чем если вы попытаетесь свернуть свою собственную.

0 голосов
/ 31 марта 2009

Если вы используете * nix, зарегистрируйте обработчик сигнала для SIGUSR1 или SIGINT в вашей C-программе, тогда из Python используйте os.kill для отправки сигнала.

...