简体   繁体   English

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

[英]Python Threading: Running 2 different functions simultaneously

I have a function foo that only stops once a condition has been met. 我有一个函数foo ,它只有在满足条件后才会停止。 While foo is running, I need to ask for user input the whole time (keeps asking for user input). foo运行时,我需要一直要求用户输入(保持提示要求用户输入)。 I want them to run separately without interfering with each other. 我希望它们分开运行而不互相干扰。

In my example below, foo keeps printing 'Hello' and getUserInput keeps looking for user input. 在下面的示例中, foo继续显示“ Hello”,而getUserInput继续查找用户输入。 I want foo to keep printing hello even if i do not enter anything for user input. 我希望foo保持打印状态,即使我没有为用户输入输入任何内容。 It will keep asking for input as long as the user does not enter letter 'e'. 只要用户不输入字母“ e”,它就会一直要求输入。 I have my attempt below: 我在下面尝试:

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()

My code prints out the first hello and asks for input but nothing after that. 我的代码打印出第一个问候,并要求输入,但此后什么也没有。 What am I doing wrong? 我究竟做错了什么? Thanks for your help in advance. 感谢您的帮助。

Update: The opener was running his code on Windows in IDLE. 更新: 开瓶器正在Windows中的IDLE中运行他的代码。 Regarding I/O it behaves differently than a shell or the Windows command line. 关于I / O,其行为与Shell或Windows命令行不同。 His code works on the Windows command line. 他的代码可在Windows命令行上使用。

In principle, your code works for me. 原则上,您的代码对我有用。 I am running Python 2.6.5. 我正在运行Python 2.6.5。

Several comments here: 这里有几条评论:

1) In your case it would be fine to only have two threads: the main thread and another one. 1)在您的情况下,最好只有两个线程:主线程和另一个线程。 However, it will also work with three. 但是,它也可以与三个一起使用。 It's just that your main thread does nothing else than waiting for the other threads to finish. 只是您的主线程除了等待其他线程完成之外没有其他操作。

2) You should to explicitly join() all threads you spawn. 2)您应该显式join()生成的所有线程。 You do this in the main thread before terminating it. 您可以在终止前在主线程中执行此操作。 Keep record of the threads you spawn (eg in a list threads ) and then join them at the end of your program (eg for t in threads: t.join() ). 记录您产生的线程(例如,在列表threads ),然后在程序末尾将它们加入(例如, for t in threads: t.join() )。

3) You share the variable self.running between threads. 3)您在线程之间共享变量self.running It is fine in this case, as one thread only reads it and another one only writes it. 在这种情况下很好,因为一个线程仅读取它,而另一个仅写入它。 In general, you need to be very careful with shared variables and acquire a lock before changing it. 通常,您需要非常小心共享变量并在更改它之前获取一个锁。

4) You should catch the KeyboardInterrupt exception in the main thread and find a way to communicate to your other threads to terminate :) 4)您应该在主线程中捕获KeyboardInterrupt异常,并找到一种与其他线程进行通信以终止的方法:)

5) Use lowercase method names, so instead of getUserInput call it get_user_input . 5)使用小写的方法名称,因此可以get_user_input代替getUserInput Use uppercase class names and inherit from object : class Test(object): 使用大写的类名并从object继承: class Test(object):

This is a running example: 这是一个正在运行的示例:

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()

When typing e or E, the program ends after a short delay (as intended by you). 键入e或E时,程序会在短暂的延迟后(根据您的预期)结束。 When pressing ctrl+c, it immediately terminates. 按ctrl + c时,它将立即终止。 Making a program that uses threading responsive to exceptions is a bit trickier than expected. 制作一个响应异常而使用threading的程序比预期的要难一些。 I have included important references in the source above. 我在上面的源代码中包含了重要的参考资料。

This is how it looks like during runtime: 这是运行时的样子:

$ python supertest.py

Hello

Enter 'e' for exit: 
Hello


Hello


Hello

e
$

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM