Как продолжить код после потока? Смущен потоком этого кода - PullRequest
0 голосов
/ 04 июля 2019

Извините, я новичок в программировании и не совсем понимаю, как работает эта тема. Моя цель состояла в том, чтобы этот вход был синхронизирован, и я нашел некоторый код, который делает это. Тем не менее, я запутался в структуре этого потока, потому что, если вы «слишком медленный», программа никогда не продолжит печатать «контрольную точку» по желанию. Это просто ... зависает ... Почему оно застревает?

import time
from threading import Thread

answer = None

def check():
    # waits for user input for 3 seconds
    for i in range(3):
        time.sleep(1)
        if answer != None:
            return
    print('too slow')

Thread(target = check).start()

answer = input("Input something: ")

print('checkpoint')

Я попробовал одну вещь:

t = Thread(target = check)
t.start()
answer = input("Input something: ")
# also tried t.join()
if t.is_alive:
    print('hi')

Я пытался решить эту программу, пытаясь вызвать и поймать исключение. Однако я не смог поймать исключение. Как мне это поймать? (Или у меня есть другое решение проблемы?)

import time
from threading import Thread

answer = None

def check():
    # waits for user input for 3 seconds
    for i in range(3):
        time.sleep(1)
        if answer != None:
            return
    print('too slow')
    # was hoping to catch this as an exception
    raise TimeoutError

# starts new thread
Thread(target = check).start()

# prompts user for an input
answer = input("Input something: ")

print('checkpoint')

Что хорошо: Когда вы вводите что-то в приглашение ввода в течение 3 секунд, оно печатает «контрольную точку» и продолжает код.

Что плохого: Если вы берете «слишком долго», программа печатает «слишком медленно!» как и ожидалось, НО тогда он прекращает выполнение кода и просто ... зависает. Поэтому, чтобы попытаться это исправить, я надеялся вызвать ошибку тайм-аута, а затем перехватить ее, но я не знаю, как ее перехватить. Это не уловило ошибку:

try:
    Thread(target = check).start()
except:
    pass

Это тоже не было:

try:
    answer = input("Input something: ")
except:
    pass

Могу ли я получить помощь? Спасибо!

Редактировать: Забыл упомянуть, что я использую Linux, поэтому многие решения для моего приложения не работали для меня, как msvcrt или клавиатура. И модули, которые работают для Linux, похоже, не являются «неблокирующими».

Ответы [ 2 ]

0 голосов
/ 06 июля 2019

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: ЭТО НЕ ОТВЕЧАЕТ НА ВОПРОС, НО В СЛУЧАЕ ВЫ ХОТИТЕ ЗНАТЬ, КАК Я ПОЛУЧИЛ «ВХОД», ЗДЕСЬ МОЕ РЕШЕНИЕ ПРОБЛЕМЫ.

На самом деле я нашел что-то, что работает!Это немного странно, но это работает для того, что я пытаюсь сделать, благодаря ответу @rayryeng здесь: обнаружить нажатие клавиши в python? .

Постановка задачи: Продолжить программу, когданажата клавиша «Ввод», и тайм-аут, если ввод занимает слишком много времени.Это именно так, хотя это странно отображается на консоли ... PS.Мне пришлось запустить это в моем терминале как «sudo», иначе это не сработает в моем скрэтч-файле по любой причине.

import curses
import os
from time import time, sleep

def main(win):
    win.nodelay(True) # True turns on "non-blocking"
    key=""
    win.clear()
    win.addstr("Please press 'Enter' to continue:")
    start_time = time()
    while 1:
        end_time = time()
        try:
            if end_time-start_time > 5: # 5 seconds
                return 'You are too slow!'

            else:
                key = win.getkey()
                if key == os.linesep:
                    return 'OK. Continuing on...'

        except Exception as e:
            # No input
            pass

p = curses.wrapper(main)
print(p) #-> either 'You are too slow!' or 'OK. Continuing on...'

Полагаю, если вы действительно хотите сохранить ввод, вы можете изменить его на что-то вроде этого:

def main(win):
    win.nodelay(True) # True turns on "non-blocking"
    key=""
    win.clear()
    win.addstr("Please press 'Enter' to continue:")
    start_time = time()
    while 1:
        end_time = time()
        try:
            if end_time-start_time > 5: # 5 seconds
                return 'You are too slow!'

            else:
                key = win.getkey() # gets a single char
                if key: # == os.linesep:
                    return str(key) # returns that single char

        except Exception as e:
            # No input
            pass

p = curses.wrapper(main)
print(p) #-> either 'You are too slow!' or character entered

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

import curses import os from time import time, sleep

def main(win):
    win.nodelay(True) # True turns on "non-blocking"
    key=""
    win.clear()
    win.addstr("Please press 'Enter' to continue:")
    start_time = time()
    result = key # empty string
    while 1:
        end_time = time()
        try:
            if end_time-start_time > 5: # 5 seconds
                return 'You are too slow!'

            else:
                key = win.getkey() # gets single char
                result = result + str(key) # adds characters to the empty string
                if key == os.linesep: # "new line"
                    return result

        except Exception as e:
            # No input
            pass

p = curses.wrapper(main)
print(p) #-> either 'You are too slow!' or characters entered
0 голосов
/ 04 июля 2019

Вы должны думать о двух потоках как о двух отдельных программах, но с одинаковыми переменными.

Поток 1 состоит из всего, что не имеет отступа в вашем коде. Он запускает поток, затем ждет ввода пользователя, затем выводит «контрольную точку». Тогда это сделано.

Поток 2 состоит из функции check. Он проверяет, не является ли переменная None. Если это произойдет, это сделано. Если этого не произойдет в течение трех секунд, будет напечатано «слишком медленно», и теперь все готово.

Ни один из потоков не "знает", что делает другой, за исключением того, что у них одна переменная, answer.

Программа в целом завершит работу, когда все ее потоки будут завершены.

Вот и все. Это то, что вы написали. Поэтому, если вы что-то печатаете, программа завершается, потому что поток 1 всегда будет выходить после того, как вы что-то наберете. Поток 2 завершается, как только видит, что переменная не None.

Если вы ничего не наберете, Тема 1 просто будет сидеть и ждать вас вечно. Вот как работает функция ввода. Поток 2 выйдет через 3 секунды или менее, но это не влияет на Поток 1.

Вы не можете выбросить исключение из одного потока в другой. Таким образом, вы не можете выбросить исключение из потока 2 и обработать его потоком 1.

Вы пытались что-то набрать ПОСЛЕ сообщения «слишком медленно»? Когда вы это сделаете, поток 1 (и, следовательно, ваша программа) выйдет.

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

...