Во-первых, вы должны выбрать, собираетесь ли вы использовать потоки или процессы.
Я не буду слишком углубляться в различия, погуглите ;) В любом случае, вот некоторые вещи, которые следует учитывать: гораздо проще установить связь между потоками, чем между процессами; в Python все потоки будут выполняться на одном и том же ядре ЦП (см. Python GIL), но подпроцессы могут использовать несколько ядер.
Процессы
Если вы используете подпроцессы, есть два способа: subprocess.Popen
и multiprocessing.Process
. С Popen
вы можете запускать что угодно, тогда как Process
предоставляет более простой потоковый интерфейс для запуска кода Python, который является частью вашего проекта в подпроцессе.
Оба могут быть убиты методом terminate
.
См. документацию для multiprocessing
и subprocess
Конечно, если вам нужен более изящный выход, вы захотите отправить подпроцессу сообщение «выход», а не просто завершить его, чтобы он получил возможность выполнить очистку. Вы можете сделать это, например. написав на его стандартный ввод. Процесс должен читать со стандартного ввода, и когда он получает сообщение «выход», он должен делать все, что вам нужно, перед выходом.
Обсуждения
Для потоков вы должны реализовать свой собственный механизм остановки, а не использовать что-то столь же жестокое, как process.terminate()
.
Обычно поток запускается в цикле, и в этом цикле вы проверяете наличие флага stop. Тогда вы выходите из петли.
У меня обычно что-то вроде этого:
class MyThread(Thread):
def __init__(self):
super(Thread, self).__init__()
self._stop_event = threading.Event()
def run(self):
while not self._stop_event.is_set():
# do something
self._stop_event.wait(SLEEP_TIME)
# clean-up before exit
def stop(self, timeout):
self._stop_event.set()
self.join(timeout)
Конечно, вам нужна некоторая обработка исключений и т. д., но это основная идея.
EDIT: ответы на вопросы в комментариях
thread.start_new_thread(your_function)
запускает новый поток, это правильно. С другой стороны, модуль threading
предоставляет API более высокого уровня, который намного удобнее.
С модулем threading
вы можете сделать то же самое с:
t = threading.Thread(target=your_function)
t.start()
или вы можете создать свой собственный класс, который наследуется от Thread
, и поместить свою функциональность в метод run
, как в примере выше. Затем, когда пользователь нажимает кнопку запуска, вы делаете:
t = MyThread()
t.start()
Вы должны где-то хранить переменную t. Где именно, зависит от того, как вы спроектировали остальную часть приложения. У меня, вероятно, был бы какой-то объект, который содержал бы все активные потоки в списке.
Когда пользователь нажимает «Стоп», вы должны:
t.stop(some_reasonable_time_in_which_the_thread_should_stop)
После этого вы можете удалить t
из своего списка, его больше нельзя использовать.
person
zvone
schedule
15.12.2015