我有个简单的应用需求:

1. 该应用随时会监听键盘的输入;

2. 当输入指定键时会控制相机录制的启动和关闭。

监听键盘是一个事件循环,相机录制也是一个循环录制的过程。我试着用 Python 启动两个进程,并用两个进程共享变量的更新来控制两个进程的交互。

监听键盘输入

首先我找到python 监听键盘输入的方案可以满足我监听键盘的需求。

 import sys, select, tty, termios

 old_attr = termios.tcgetattr(sys.stdin)
tty.setcbreak(sys.stdin.fileno())
print('Please input keys, press Ctrl + C to quit') while(1):
if select.select([sys.stdin], [], [], 0)[0] == [sys.stdin]:
print(sys.stdin.read(1)) termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_attr)

这段代码可以进行键盘监听,但是却有一个潜在 Bug第 11 行的代码永远无法执行,即使加上跳出循环的判断,当使用 Ctrl+C 时程序会终止。

而第 11 行的作用是恢复当前终端的原始属性,没执行到该语句,终端会变得不正常:你会发现程序结束后在该终端输入字符不会有显示。因此,程序应该设法程序终止时必然执行该语句

我建议改为类似的代码来修复这个 Bug:

 import sys
import select
import tty
import termios old_attr = termios.tcgetattr(sys.stdin)
tty.setcbreak(sys.stdin.fileno())
print('Please input keys, press Ctrl + C to quit') try:
while True:
if select.select([sys.stdin], [], [], 0)[0] == [sys.stdin]:
key = sys.stdin.read(1)
if key == 'q':
# to stop the infinite loop
break
elif key == 's':
# do something
print('I will do something')
else:
# do other things
print(key) except Exception as e:
print(e)
finally:
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_attr)

相机录制

相机录制的路径当然因不同的相机而异,因此这里我只写 Demo 级别的抽象代码:

 import time

 class Recorder:
def __init__(self):
print('Recorder initialization.') def run(self):
time.sleep(0.3)
print('Recording a frame.') def close(self):
print('Recording ended.') recorder = Recorder() t0 = time.time()
while time.time() - t0 < 10:
recorder.run() recorder.close()

可以看到这段逻辑也有一个条件循环。

假设应用的需求是按键 s,进行录制;再次按键 s,终止录制。

由于这两个逻辑需要完全同时进行,而 Python 的线程又是伪并行,因此这里考虑用多进程共享变量的通信。

使用进程间共享变量

使用 multiprocessing,直接看完整的代码是比较直观的:

 import time
import sys
import select
import tty
import termios
import multiprocessing class Recorder:
def __init__(self):
print('Recorder initialization.') def run(self):
time.sleep(0.3)
print('Recording a frame.') def close(self):
print('Recording ended.') def recording_process(shared):
recorder = Recorder()
while shared['is_recording']:
recorder.run() recorder.close() if __name__ == '__main__':
# set shared variable
manager = multiprocessing.Manager()
shared = manager.dict()
shared['is_recording'] = False old_attr = termios.tcgetattr(sys.stdin)
tty.setcbreak(sys.stdin.fileno())
print('Please input keys, press Ctrl + C to quit') # check the keyborad
p = None
try:
while True:
if select.select([sys.stdin], [], [], 0)[0] == [sys.stdin]:
key = sys.stdin.read(1)
if key == 'q':
# to stop the infinite loop
break
elif key == 's':
# toggle
shared['is_recording'] = not shared['is_recording']
# resume or stop recording
if shared['is_recording']:
p = multiprocessing.Process(target=recording_process, args=(shared,))
p.start()
else:
p and p.join()
else:
# do other things
print(key) except Exception as e:
print(e)
finally:
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_attr)

原文作者:雨先生
原文链接:https://www.cnblogs.com/noluye/p/11704982.html  
许可协议:知识共享署名-非商业性使用 4.0 国际许可协议

参考

Python使用进程间共享变量来控制两个进程(监听键盘和相机录制)的交互的更多相关文章

  1. Python进阶----进程间数据隔离, join阻塞等待, 进程属性, 僵尸进程和孤儿进程, 守护进程

    Python进阶----进程间数据隔离, join阻塞等待, 进程属性, 僵尸进程和孤儿进程, 守护进程 一丶获取进程以及父进程的pid 含义:    进程在内存中开启多个,操作系统如何区分这些进程, ...

  2. android 进程间通信 messenger 是什么 binder 跟 aidl 区别 intent 进程间 通讯? android 消息机制 进程间 android 进程间 可以用 handler么 messenger 与 handler 机制 messenger 机制 是不是 就是 handler 机制 或 , 是不是就是 消息机制 android messenge

    韩梦飞沙  韩亚飞  313134555@qq.com  yue31313  han_meng_fei_sha messenger 是什么 binder 跟 aidl 区别 intent 进程间 通讯 ...

  3. Python 进程间的通信

    #-*-coding:utf-8-*- '''python提供了多种进程间的通信方式,如:Queue,Pipe,Valie+Array等. Queue与Pipe的区别在于Pipe常用来在两个进程间通信 ...

  4. Android查缺补漏(IPC篇)-- 进程间通讯基础知识热身

    本文作者:CodingBlock 文章链接:http://www.cnblogs.com/codingblock/p/8479282.html 在Android中进程间通信是比较难的一部分,同时又非常 ...

  5. Python多进程编程-进程间协作(Queue、Lock、Semaphore、Event、Pipe)

    进程与进程之间是相互独立的,互不干扰.如果多进程之间需要对同一资源操作,就需要进程间共享变量,上一篇文章介绍了进程间共享数据的三大类Value.Array.Manager,这三种类的主要区别在于管理的 ...

  6. Python之路(第三十九篇)管道、进程间数据共享Manager

    一.管道 概念 管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信. 先画一幅图帮助大家理解下管道的基本原理 现有2个 ...

  7. Python 多进程编程之 进程间的通信(在Pool中Queue)

    Python 多进程编程之 进程间的通信(在Pool中Queue) 1,在进程池中进程间的通信,原理与普通进程之间一样,只是引用的方法不同,python对进程池通信有专用的方法 在Manager()中 ...

  8. python 使用多进程实现并发编程/使用queue进行进程间数据交换

    import time import os import multiprocessing from multiprocessing import Queue, pool ""&qu ...

  9. Py修行路 python基础 (二十五)线程与进程

    操作系统是用户和硬件沟通的桥梁 操作系统,位于底层硬件与应用软件之间的一层 工作方式:向下管理硬件,向上提供接口 操作系统进行切换操作: 把CPU的使用权切换给不同的进程. 1.出现IO操作 2.固定 ...

随机推荐

  1. map、set 使用方法 | 1022 图书馆信息查询

    看了答案才知道了这题的各种骚操作,然后敲了一顿骚键盘,然后wa.调了很久,才发现要规格化打印……mdzz…… 注:加粗代码为傻逼规格化打印代码: #include <stdio.h> #i ...

  2. MACbook安装WIN7后亮度调节的办法

     MACbook安装WIN7后亮度调节的办法:1.按WIN+X打开移动中心,第一个就是亮度调节.或者右击托盘区的电池,选择移动中心也可以.2.右击托盘区域的电池,选择电源管理,在界面中调节亮度. 3. ...

  3. AtCoder Grand Contest 037题解

    传送门 \(A\) 直接把每个字母作为一个字符串,如果某个串和它前面的相同,那么就把这个字母和它后面那个字母接起来.然而我并不会证明这个贪心的正确性 //quming #include<bits ...

  4. ZROI 暑期高端峰会2019 总结

    FBI Warning:以下博客含有 FBI Warning 的都是包含大量人类本质之一的. 前几天听课: Day1 组合计数 Day1 序列数据结构 Day2 线性代数 Day3 图论 Day3 字 ...

  5. [LeetCode] 737. Sentence Similarity II 句子相似度之二

    Given two sentences words1, words2 (each represented as an array of strings), and a list of similar ...

  6. IDEA中把普通的Java项目转换成gradle项目

    1.在该项目的跟目录下创建build.gradle 和 settings.gradle文件,内容如下: build.gradle: plugins { id 'java' } group 'coco' ...

  7. css 在一定区域内滚动显示,不修改父级样式

    做项目时,会遇到一些零碎的技术点.记录下来以防忘记 需求:图中圈中的部门是滚动的.不修改父级样式 代码: <div class="right-text-bottom"> ...

  8. HTML连载28-标签的权重

    一.什么是优先级的权重 1.作用:当多个选择器混合在一起的时候,我们可以通过计算权重来判断谁的优先级最高. 2.权重的计算规则 公共代码: <body> <div id=" ...

  9. IDEA Rider 准备试用一段时间(1)

    IDEA Rider是一个C#开发工具,目前最高版本支持C# 8.0语法. IDEA Rider2019.2月版本相比之前2018版本多了新功能,又支持Edit and Continue,所以准备试用 ...

  10. 第七节:EF Core调用SQL语句和存储过程

    一. 查询类(FromSql) 1.说明 A. SQL查询必须返回实体的所有属性字段. B. 结果集中的列名必须与属性映射到的列名相匹配. C. SQL查询不能包含关联数据 D. 除Select以为的 ...