起因:
公司有一个小项目。 大概逻辑如下。服务器a继续向队列推送消息。 消息的主要内容是视频地址。 服务器b必须继续对队列中的消息进行pop,然后剪辑该视频并将最终剪辑的视频保存到云服务器。 个人主要实现b服务器逻辑。
实现思路:
1线程池进程请求1 :主进程必须作为守护进程运行。
请求点2 :利用线程池,设定最大同时运行的工作器,各线程通过调用subprocess的Popen来执行wget ffprobe ffmpeg等命令处理视频。
2消息队列采用redis的list实现
3个主线程在从队列中获取消息后,从线程池中获取空闲的从线程(在此,将非主线程统称为从线程。 以下相同) ) ),从线程对该消息进行某种逻辑处理后,生成流程以剪切视频,最后上载视频。
要求点daemon收到signint信号时,为了在处理当前正在进行的工作器后关闭,并且不浪费队列中的数据,必须在主进程有空闲工作器时从队列中检索数据
大致是这样的:
基本上,主要资源用于视频下载和视频处理,同时运行的工作器(来自线程)很少。 如果有几个典型的cpu,则设置几个工作器。
上面共有三个要求点,其中要求点2不费事。 所以无视。
实现
要点1的实现:
第3点的实现:
线程池,采用python的futures模块。 这个模块提供了线程池机制。 说一点他的线程池的实现原理吧。 ThreadPoolExecutor类实现了线程池:
1每个实例本身都有_work_Queue属性。 这是存储任务的队列对象。
2每次调用此对象的submit方法时,都将任务放入_work_queue中,并从线程生成任务,直到达到线程数max_worker中设置的值。
3线程池实例中的所有从属线程从_work_queue获取任务并继续执行。 来自线程的daemon属性也设置为True
重点是那个嵌套的while循环。
踩坑收割:
1 python只能处理主线程的信号。 如果使用线程中的连接方法阻止主线程,则来自从属线程的执行时间过长可能会导致信号无法长时间处理。 所以尽量把来自线程的daemon设为True。
2 Queue的下层为deque,而deque的下层为双重链接列表。 为什么要用双链接列表而不是list? 答案请在参考中寻找。
学习了用daemon方式运行进程的方法。
1 pid文件的源
fdgb和工艺组的概念
3信号的捕获
4 dup2函数和fcntl函数
4个进程由Popen ()创建时,使用PIPE作为子进程(stdin stdout stderr )与父进程交互时,下一次调用wait时,会被子进程的stdin stdout stderr卸载原因也在参考中寻找。
5 sudo运行脚本时,环境变量去了哪里? 请参考寻找答案
6 python的唤醒模块很方便呢