Python在循环执行其他代码时捕获用户输入?

时间:2017-01-13 21:14:56

标签: python

我在循环中运行顺序代码,进行各种计算,偶尔打印出我在控制台中监视的结果。

我想做的是能够在程序运行时点击键盘按钮,然后在下一次开始迭代时保存并处理该输入(例如,作为更改某些参数的命令)环。

这是我运行的代码的结构:

for i in range(0, itrs):
    # ideally at the start of each loop: 
    # check to see if user pressed keybutton during prev loop itr, 
    # but don't wait / poll for it! 

    # userKeyInput = checkIfUserPressedKey()
    # param = modify(userKeyInput)

    doSequentialComputation(param)

解决方案是否会涉及一些线程或中断的概念?我可能想出一个涉及文件I / O的解决方案,这不会很糟糕,但我想可能Python有一些更简单的工作方式。

谢谢!

2 个答案:

答案 0 :(得分:1)

使用线程运行doSequentialComputation函数并将param作为线程参数传递给它:

import threading
t = threading.Thread(target=doSequentialComputation, args=(param,))
t.daemon = True
t.start()

主线程中param的任何修改都将被线程中的代码看到。请务必使用param

保护对threading.Lock的访问权限
param_lock = threading.Lock()
userKeyInput = checkIfUserPressedKey()
with param_lock:
    parm = modify(userKeyInput)

全部放在一起:

import threading

class Parameter(object):
    pass

def doSequentialComputation(param, param_lock):
    itrs = 1000
    param_copy = None
    with param.lock:
        param_copy = param
    for i in range(0, itrs)
        with param.lock:
            if param.has_changed:
                param_copy = param
                param.has_changed = False
        compute(param_copy)

def main():
    param = Parameter()
    param.has_changed = False
    param.lock = threading.Lock()
    args=(param, param_lock)
    compute_thread = threading.Thread(target=doSequentialComputation, args=args)
    compute_thread.daemon = True
    compute_thread.start()
    while True:
        userKeyInput = checkIfUserPressedKey()
        with param.lock:
            param = modify(userKeyInput, param)
            param.has_changed = True

Parameter类允许我们创建一个可以添加任意属性的对象。

答案 1 :(得分:1)

如果你希望python同时做两件事(获取用户输入和计算),最简单的事情就是使用单独的线程(在这个例子中,单独的进程更难,不需要)。高级threading库非常容易上手,我建议docs一次性完成,但这是一个简单的例子:

from threading import Thread,Lock
import time

class globalVars():
    pass

G = globalVars() #empty object to pass around global state
G.lock = Lock() #not really necessary in this case, but useful none the less
G.value = 0
G.kill = False

def foo(n): #function doing intense computation
    for i in range(n):
        if G.kill:
            G.kill = False
            return
        time.sleep(n) #super intense computation
        with G.lock:
            G.value += i

t = Thread(target=foo, args=(10,))
t.start()

def askinput():
    #change to raw_input for python 2.7
    choice = input("1: get G.value\n2: get t.isAlive()\n3: kill thread\nelse: exit\ninput: ")
    if choice == "1":
        with G.lock:
            print(G.value)
    elif choice == "2":
        print(t.is_alive())
    elif choice == "3":
        G.kill = True
    else:
        return 0
    return 1

while askinput():
    pass