在开发python服务中,经常会遇到不再等待实际任务运行,需要提前返回。
比如,图像生成、LLM调用,这类任务运行时间较长。
一般主程序在异步启动实际任务后,会提前退出,然后隔一段时间轮询一次,检查任务是否完成。
python有多种方式实现异步执行,这里通过threading方式实现异步执行。
首先示例正常运行程序,然后尝试改为threading异步版本。
所用示例代码参考和修改自网络资料。
1 同步调用
1.1 同步运行分析
这是一个正常运行的程序,在main中以顺序执行的方式,分别运行阻塞程序1、阻塞程序2。
由于不涉及异步执行,所以没有实际用到threading包。
同步运行控制简单,存在的问题是一个时间段只能运行一个程序,效率较低。
1.2 同步运行示例
这是同步运行程序的示例代码
import threading,time
def thead(num):
time.sleep(1)
print("阻塞程序%s开始执行"%num)
time.sleep(3)
print("阻塞程序%s执行完毕"%num)
def main():
print("主方法开始执行")
for i in range(1, 3):
thead(i)
print("主方法执行完毕")
return
if __name__ == '__main__':
print(time.ctime())
num = main()
print("返回结果为%s"%num)
print(time.ctime())
如下所示,首先程序1运行开始,程序1结束,然后程序2开始,程序2结束,整个过程顺序进行。
Thu Dec 4 09:50:42 2025
主方法开始执行
阻塞程序1开始执行
阻塞程序1执行完毕
阻塞程序2开始执行
阻塞程序2执行完毕
主方法执行完毕
返回结果为None
Thu Dec 4 09:50:50 2025
2 异步调用
2.1 异步运行分析
由于一些实际需求,主方法main可能需要在启动程序1和程序2后提前退出。
这个时候就会用到python threading的异步执行功能。
主方法main通过threading分别为程序1和程序2创建线程1和线程2,示例代码如下。
poll = []#线程池
for i in range(1,3):
thead_one = threading.Thread(target=thead, args=(i,))
poll.append(thead_one) #线程池添加线程
然后,主方法main在分别异步启动线程1和线程2,示例代码如下。
for n in poll:
n.start() #准备就绪,等待cpu执行
启动完成后,主方法main就可以提前退出了。
print("主方法执行完毕")
return
主方法main退出后,线程1和线程2可能还在异步运行。
异步运行控制复杂,然而可减少主程序等待,在同一时间段并发运行多个程序,效率高。
2.2 异步运行示例
这是异步运行程序的示例代码。
import threading,time
def thead(num):
# time.sleep(1)
print("线程%s开始执行"%num)
time.sleep(3)
print("线程%s执行完毕"%num)
def main():
print("主方法开始执行")
#创建2个线程
poll = []#线程池
for i in range(1,3):
thead_one = threading.Thread(target=thead, args=(i,))
poll.append(thead_one) #线程池添加线程
for n in poll:
n.start() #准备就绪,等待cpu执行
print("主方法执行完毕")
return
if __name__ == '__main__':
print(time.ctime())
num = main()
print("返回结果为%s"%num)
print(time.ctime())
输出如下所示,
主方法在启动线程1、线程2后就退出
线程1、线程2转为后台并发运行,其退出时间可以晚于主方法的退出时间。
然而,线程1、线程2同时并行运行,能减少等待时间,提高运行效率。
Thu Dec 4 10:02:29 2025
主方法开始执行
线程1开始执行
线程2开始执行
主方法执行完毕
返回结果为None
Thu Dec 4 10:02:29 2025
线程1执行完毕
线程2执行完毕
reference
python线程实现异步任务
https://www.cnblogs.com/lyxdw/p/9993293.html
python使用async和await并发编程示例