在 Python 中使用计时器和线程创建辅助命令行应用程序 [英] Using Timers and Threads in Python to create assistive command line application

查看:41
本文介绍了在 Python 中使用计时器和线程创建辅助命令行应用程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

让我描述一下我的场景:

我正在为教学系统开发一个基于命令行的概念验证,我正在用 Python 编写它.系统的工作原理是行为心理学.我奖励用户(有特殊需求的孩子)的正确答案,我给他们纠正错误答案的后果.如果他们正在努力寻找答案,我还需要提供答案提示.

这是我的应用程序的高级伪代码:

<块引用>

试用:

  1. 提出诸如草是什么颜色的?"之类的问题.
  2. 等待回答
    一种.如果在 n 秒内未提供答案,则发出帮助提示(例如Gr, Gree")
    湾如果在 n+m 秒内未提供答案,则发出更正结果.(例如,草的颜色是绿色的.让我们再试一次.")并重复该过程
    C.如果在任何 n 或 n+m 时间内提供正确答案,请表扬学生并重复该过程.
    d.如果在任何 n+m 时间内提供了不正确的答案,则发出更正结果并重复试验.

  3. 结束审判

这是我的观察和一个困境:

一旦我向学生提出问题,我就在等待事件自行发生,或者等待超时.我也应该在等待期间发出提示.

到目前为止,在我的主要流程中,我使用了两个 threading.Timer 对象,一个在 n 秒后发出提示,另一个在 n+m 期间未发生答案时发出纠正结果.

如果答案在 n 或 n+m 时间内发生,我会取消计时器.

然而,我的问题与主要流程有关.如果答案等待超时发生,我也想取消等待答案.就像我取消计时器一样,如果我的最终无应答超时发生,我也想取消在命令行上等待输入.

我想拥有一个 threading.Thread (get_answer) 和两个计时器(provide_hint、timeout_wait).

线程 get_answer 正在等待来自命令行的响应.

如果 n 秒后没有回答,第一个计时器 (provide_hint) 会向用户发出提示.

第二个计时器 (timeout_wait) 将取消线程 (get_answer),如果在 n+m 秒后没有响应.

如果答案发生正确或错误,线程 get_answer 可以取消两个计时器.

我在这里的问题是:

A) 我的并发数据结构是否正确使用,您还有其他建议吗?

B) 是否存在任何可能的死锁问题以及如何避免它们?

提前致谢.

解决方案

这里有一个不使用线程的解决方案.它在 Linux 上进行了测试,但可能适用于任何地方(但我不确定 Windows).它安排发送一个 SIGALRM 信号.

导入信号类警报(异常):经过def stop_me(*args):报警信号.信号(信号.SIGALRM,stop_me)def raw_input_with_timeout(超时):尝试:signal.alarm(timeout) # 秒数尝试:返回原始输入()最后:signal.alarm(0) # 停止闹钟除了警报:返回警报!"# 或任何东西

这不是最终的解决方案,因为存在一些问题:如果用户已经输入了一行的一部分,SIGALRM 将中断它,但他到目前为止输入的内容仍保留在终端的读取缓冲区中.它将成为下一个 raw_input() 返回内容的一部分.您可能必须将终端设为原始模式以避免这种情况.请参阅关于生终端模式与熟终端模式的混淆?.

Let me describe my scenario:

I am developing a command line-based proof-of-concept for the instructional system, and I am writing it in Python. System works on the principles of behavioral psychology. I am rewarding users (children with special needs) for correct answers, and I am giving them correcting consequences for the wrong answers. I am also needing to provide hints to answers if they are struggling with answers.

Here is a high level pseudo code for my application:

Trial:

  1. Ask question such as 'What color is grass?'
  2. wait for answer
    a. If answer not provided within n seconds issue helping hint (e.g. "Gr, Gree")
    b. If answer is not provided within n+m seconds issue a corrective consequence. (e.g.,"Color of the grass is green.Let's try it again. ") and repeat the process
    c. If correct answer is provided during any n or n+m time praise the student and repeat the process.
    d. If the incorrect answer is provided during any of the n+m time, issue a corrective consequence and repeat the trial.

  3. Conclude the trial

So here is my observation and a dilemma:

Once I issue a question to student, I am waiting for events to happen on their own, or for my waiting to time out. I am also supposed to issue a hint during the wait period.

So far, in my main flow I used two threading.Timer objects, one to issue hint after n seconds and another one to issue corrective consequence if the answer never happens during the n+m period.

If answer happens of any kind during n or n+m time, I cancel the timers.

My question, however, is related to the main process. I also want to cancel the waiting on the answer if the answer waiting time-out happen. Just as I cancel timers, I also want to cancel waiting on the command line for the input if my final no-answer timeout occurs.

I am thinking to have one threading.Thread (get_answer) and two Timers (provide_hint, timeout_wait).

Thread get_answer is waiting on a response from a command line.

First timer (provide_hint) is giving a hint to user if there is no answer after n seconds.

Second timer (timeout_wait) is canceling out the thread (get_answer) if no answer happens after some period of n+m seconds.

Thread get_answer can cancel both timers if the answer happens be it correct or incorrect.

Questions I have here are:

A) Are my concurrent data structures correctly used and do you have any other suggestions?

B) Are there any possible deadlock issues and how to avoid them?

Thanks in advance.

解决方案

Here is a solution without using threads. It was tested on Linux, but probably works everywhere (but I'm unsure about Windows). It arranges for a SIGALRM signal to be delivered.

import signal

class Alarm(Exception):
    pass
def stop_me(*args):
    raise Alarm
signal.signal(signal.SIGALRM, stop_me)

def raw_input_with_timeout(timeout):
    try:
        signal.alarm(timeout)  # number in seconds
        try:
            return raw_input()
        finally:
            signal.alarm(0)   # stop the alarm
    except Alarm:
        return "alarm!"   # or anything

It's not a final solution because there are issues: if the user already typed part of a line, a SIGALRM will interrupt it, but what he typed so far remains in the read buffer of the terminal. It will be part of what the next raw_input() returns. You may have to turn the terminal in raw mode to avoid that. See Confusion about raw vs. cooked terminal modes? .

这篇关于在 Python 中使用计时器和线程创建辅助命令行应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆