взаимодействие с длительно выполняющимися задачами на python

StackOverflow https://stackoverflow.com/questions/700073

Вопрос

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

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

Какой бы вы сочли наилучшим подходом к решению такого рода проблем?Я могу изменить код как на python, так и на C-сторонах.

Это было полезно?

Решение

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

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

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

Другие советы

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top