Python线程:同时运行2个不同的函数

Aas*_*daq 4 python multithreading

我有一个功能foo,只有在满足条件后才会停止.在foo运行时,我需要一直询问用户输入(不断询问用户输入).我希望它们分开运行而不会相互干扰.

在下面的示例中,foo继续打印"Hello"并getUserInput继续查找用户输入.即使我没有为用户输入输入任何内容,我也希望foo继续打印你好.只要用户没有输入字母'e',它就会一直询问输入.我有以下尝试:

import threading
from time import sleep

class test:
    def __init__(self):
        self.running = True

    def foo(self):
        while(self.running):
            print 'Hello\n'
            sleep(2)

    def getUserInput(self):
        x = ''
        while(x != 'e'):
            x = raw_input('Enter value: ')
        self.running = False

    def go(self):
        th1 = threading.Thread(target=self.foo)
        th2 = threading.Thread(target=self.getUserInput)
        th1.start()
        th2.start()


t = test()
t.go()
Run Code Online (Sandbox Code Playgroud)

我的代码打印出第一个问候语并要求输入,但之后没有任何内容.我究竟做错了什么?感谢您的帮助.

Jan*_*cke 6

更新: 开启者在IDLE上的Windows上运行他的代码.关于I/O,它的行为与shell或Windows命令行不同.他的代码适用于Windows命令行.

原则上,您的代码适合我.我正在运行Python 2.6.5.

这里有几条评论:

1)在你的情况下,只有两个线程是好的:主线程和另一个线程.但是,它也可以使用三个.只是你的主线程只是等待其他线程完成.

2)您应该明确显示join()您生成的所有线程.您在终止它之前在主线程中执行此操作.记录您产生的线程(例如在列表中threads),然后在程序结束时加入它们(例如for t in threads: t.join()).

3)您self.running在线程之间共享变量.在这种情况下它很好,因为一个线程只读取它而另一个只写它.通常,您需要非常小心共享变量并在更改之前获取锁定.

4)你应该KeyboardInterrupt在主线程中捕获异常并找到一种方法与你的其他线程进行通信以终止:)

5)使用小写方法名称,而不是getUserInput调用它get_user_input.使用大写的类名并继承自object:class Test(object):

这是一个运行的例子:

import threading
from time import sleep


def main():
    t = Test()
    t.go()
    try:
        join_threads(t.threads)
    except KeyboardInterrupt:
        print "\nKeyboardInterrupt catched."
        print "Terminate main thread."
        print "If only daemonic threads are left, terminate whole program."


class Test(object):
    def __init__(self):
        self.running = True
        self.threads = []

    def foo(self):
        while(self.running):
            print '\nHello\n'
            sleep(2)

    def get_user_input(self):
        while True:
            x = raw_input("Enter 'e' for exit: ")
            if x.lower() == 'e':
               self.running = False
               break

    def go(self):
        t1 = threading.Thread(target=self.foo)
        t2 = threading.Thread(target=self.get_user_input)
        # Make threads daemonic, i.e. terminate them when main thread
        # terminates. From: http://stackoverflow.com/a/3788243/145400
        t1.daemon = True
        t2.daemon = True
        t1.start()
        t2.start()
        self.threads.append(t1)
        self.threads.append(t2)


def join_threads(threads):
    """
    Join threads in interruptable fashion.
    From http://stackoverflow.com/a/9790882/145400
    """
    for t in threads:
        while t.isAlive():
            t.join(5)


if __name__ == "__main__":
    main()
Run Code Online (Sandbox Code Playgroud)

键入e或E时,程序会在短暂延迟后结束(按照您的意图).按ctrl + c时,它会立即终止.制作一个使用threading响应异常的程序比预期的要复杂一些.我在上面的源代码中包含了重要的参考资料.

这是它在运行时的样子:

$ python supertest.py

Hello

Enter 'e' for exit: 
Hello


Hello


Hello

e
$
Run Code Online (Sandbox Code Playgroud)

  • IDLE可能在等待输入时阻止输出.所以你的线程可能正在尝试打印'hello'但是空闲不会让它直到输入得到解决.是的,在命令行中运行它 (2认同)