非阻塞的Python进程或线程

29 投票
3 回答
50036 浏览
提问于 2025-04-16 21:27

我有一个简单的应用程序,它会监听一个网络连接。每当收到特定的数据时,就会调用一个回调函数,并把这些数据传给它。在这个回调函数里,我想把我的数据发送到另一个进程或线程去处理,因为处理这些数据可能需要很长时间。我最开始是在回调函数里直接运行代码,但这样会导致程序卡住!!

那我应该怎么正确地开启一个新任务呢?

3 个回答

3
    import threading
    from   time import sleep
    import sys

    # assume function defs ...

    class myThread (threading.Thread):
        def __init__(self, threadID):
            threading.Thread.__init__(self)
            self.threadID = threadID
        def run(self):
            if self.threadID == "run_exe":
                run_exe()

    def main():
        itemList = getItems()

        for item in itemList:
            thread = myThread("run_exe")
            thread.start()
            sleep(.1)
            listenToSocket(item)
            while (thread.isAlive()):
                pass # a way to wait for thread to finish before looping
    main()
    sys.exit(0)

在调用thread.start()和listenToSocket(item)之间加个睡眠时间,确保线程已经建立好,然后再开始监听。这个代码我是在一个单元测试框架中实现的,因为我需要启动多个不阻塞的进程(也就是len(itemList)次),因为我的另一个测试框架(listenToSocket(item))是依赖这些进程的。

un_exe()可以触发一个子进程的调用,这个调用可能会阻塞(比如说调用pipe.communicate()),这样执行的输出数据就能和Python脚本的输出保持同步。不过,线程的特性让这个问题变得可以接受。

所以这段代码解决了两个问题——在不阻塞脚本执行的情况下打印子进程的数据,以及动态地顺序创建和启动多个线程(如果我以后要往itemList里添加更多项目,这样维护脚本会更方便)。

6

多进程模块里有一个叫做工作池的东西。如果你不需要使用工作池的话,可以直接用进程来让某些任务和你的主程序同时运行。

37

threading 是一个常用的库,用于处理基于资源的多线程编程。还有一个库叫 multiprocessing,它主要是为了执行需要大量计算的并行任务而设计的;不过在你的情况下,通常推荐使用 threading 库。

示例

import threading, time
def my_threaded_func(arg, arg2):
    print "Running thread! Args:", (arg, arg2)
    time.sleep(10)
    print "Done!"

thread = threading.Thread(target=my_threaded_func, args=("I'ma", "thread"))
thread.start()
print "Spun off thread"

撰写回答