Найти - Пользователи
Полная версия: Завершение основного потока из дочернего.
Начало » Python для экспертов » Завершение основного потока из дочернего.
1 2
Anatolich
Цель задачи использовать таймер в роле watchdog, который завершит исполнение скрипта в случае бездействия пользователя или простоя скрипта. Два мои примера ниже, не работаю как я хочу, помогите решить задачу.

Тут по exit(0) работа не завершается.
 import threading
import msvcrt
import time
stop = True
def time_th():
    global stop
    while stop:
        stop = False
        for i in range(5,0,-1):
            time.sleep(2)
            print(i)
    exit(0)
trh =  threading.Thread(target=time_th)
trh.start()
key = None
while key != b'\x1b':
    key = msvcrt.getch()
    stop = True
    print(key)

Тут после timer.run(), код вообще не отрабатывает.
 import threading
import msvcrt
import time
class time_(threading.Thread):
    def __init__(self, ):
        super(time_, self).__init__()
        self.t_worck = True
    def run(self):
        while self.t_worck:
            self.t_worck = False
            for i in range(5,0,-1):
                time.sleep(2)
                print(i)
        exit(0)
    def m_continue(self):
        self.t_worck = True
timer = time_()
timer.run()
key = None
while key != b'\x1b':
    key = msvcrt.getch()
    timer.m_continue()
    print(key)
Anatolich
Господа специалисты, неужели непосильная задача для вас или для Python-а?
PEHDOM
Anatolich
Два мои примера ниже, не работаю как я хочу, помогите решить задачу.
давайте по порядку, как вы хотите чтобы оно работало?
Anatolich
Тут по exit(0) работа не завершается.
а что должна? у вас же еще цикл while key != b'\x1b': крутится, и программа не завершит свою работу пока key != b'\x1b'
exit(0) вообще там не сработает ну ни в какую, он просто вызовет выход из потока. https://stackoverflow.com/questions/905189/why-does-sys-exit-not-exit-when-called-inside-a-thread-in-python
Можно его заменить на os._exit(1) но он убьет ваш скрипт напрочь и мгновенно, так что никакие “финальные” блоки(например закрытие файла если вы его открыли через менеджер контекста with) не успеют отработать. Если вас это устраивает, то это по сути единственныый способ реализовать вот это все в вашей ситуации,(под юникслайк ОС есть еще вариант через signal попробовать https://stackoverflow.com/questions/492519/timeout-on-a-function-call) иначе нужно пересматривать архитектуру. Например посмотреть в сторону asyncio.
Anatolich
давайте по порядку, как вы хотите чтобы оно работало?

Задача.
Есть удаленный linux сервер, на нем необходимо запускать скрипт, который имеет простое TUI меню, переход по пунктам меню осуществляется вводом номера пункта с клавиатуры(ожидаю в цикле нужные мне клавиши), если пользователь вышел из удаленной сессии или сессия завершилась по тайм-ауту, но скрипт не был завершен, он будет висеть в памяти. Задача такая, нужен некий таймер, который в случае бездействия пользователя, например 5 минут, завершит скрипт.
PEHDOM
Anatolich ой шото вы недоговаривате, ибо я испытываю когнитивный диссонанс читая:
Anatolich
Есть удаленный linux сервер
и
Anatolich
import msvcrt
msvcrt виндовая приблуда и под линуксом работать не будет.
Если реально под линуксом то там многопоточность не нужна, можно обойтись сигналами, както так:
 #!/usr/bin/python3
# -*- coding: utf-8 -*-
import os
import signal
import time
IDLE_TIMEOUT = 10   # таймаут бездействия в секундах
CHECK_INTARVAL = 2 # интерал проверки таймаута в секундах
def handler(signum, frame):
    idle_time = time.time() - last_activity  # время простоя
    if idle_time > IDLE_TIMEOUT:   # если время простоя больше таймаута бездействия
        exit(0)
    else:                                      # иначе запустить повторно проверку через CHECK_INTARVAL секунд
        signal.alarm(CHECK_INTARVAL)
signal.signal(signal.SIGALRM, handler)
signal.alarm(CHECK_INTARVAL)
last_activity = time.time()
key = None
while key != 'b':   # тут выполняется какаято работа
    key = input('press a key')
    last_activity = time.time()
    print(key)
JOHN_16
Что то я не понял. Говорите сервер на линуксе, при этом используете msvcrt
msvcrt — Useful routines from the MS VC++ runtime

These functions provide access to some useful capabilities on Windows platforms.
Это не должно работать.

А вообще, можно конечно и потоки, но это всегда сложнее, чем написать просто линейный код. Вот прям сходу я могу предложить следующий очень простой вариант.
Вы пишите 2 программы. Первая это ваше TUI приложение. Оно должно как им то образом уведомлять о том что юзер активный. Судя по описанию, таким может быть факт нажатия пользователем клавиши. Пускай по нажатию клавиши будет создаваться временный файл (более продвинуто использовать unix сокеты) c именем /tmp/mytui/123, где 123 это PID процесса. А в сам файл пишется текущее время. На старте программы тоже такое надо сделать, что бы было начальное значение.
Вторая программа это тот самый watcher, в цикле раз в N времени ищется с помощью модуля glob файл в директории /tmp/mytui и считывает в них время. Если разница текущего времени с записанным более выбранного вами порога, то зная из имени файла pid процесса шлем ему сигнал о завершении и удаляем файл.
Это прям на мой взгляд одно из самых простых и доступных решений.
JOHN_16
PEHDOM
я сперва тоже хотел предложить ровно то, но после того как увидел о том что там используется msvcrt изменил мнение, в торону более простого. (ну как то “не уровень” у ТС, может и тот код не сам писал, а взял откуда то)
Anatolich
Господа не зацикливайтесь на msvcrt, это примеры, их я тестил на Win.
А вообще желательно решение кроссплатформенное (Возможна предстоит работа на удаленных Win серверах) и на python2.7
PEHDOM
Anatolich
А вообще желательно решение кроссплатформенное и на python2.7
А чем не устраивают три предложеных выше решения?
Anatolich
А кто сказал, что не устраивает? Я до утончил задачу и пояснил использовании msvcrt.

Оно собственно и с os._exit(0) работает, пост #3.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB