我有个简单的应用需求:

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. 数据结构——顺序队列(sequence queue)

    /* sequenceQueue.c */ /* 顺序队列 */ #include <stdio.h> #include <stdlib.h> #include <std ...

  2. python中使用rsa加密

    前提不多说, 为什么使用RSA加密请自行搜索,直接正为: 一. 生成公钥及私钥, 并保存 二. 使用公钥加密, 私钥解密 后记: 通常使用中, 会先对数据进行bas64加密, 再对加密后的内容使用rs ...

  3. 【转】机器学习实战之K-Means算法

    一,引言 先说个K-means算法很高大上的用处,来开始新的算法学习.我们都知道每一届的美国总统大选,那叫一个竞争激烈.可以说,谁拿到了各个州尽可能多的选票,谁选举获胜的几率就会非常大.有人会说,这跟 ...

  4. wait函数和waitpid的使用和总结

    wait和waitpid出现的原因 SIGCHLD --当子进程退出的时候,内核会向父进程发送SIGCHLD信号,子进程的退出是个异步事件(子进程可以在父进程运行的任何时刻终止) --子进程退出时,内 ...

  5. zr2019暑期高端峰会AB组十测

    郑睿round 1 代码真的好写,还是太笨了,爆零了. 郑睿round_2 好失败,A题真的是日狗了,第一发就可以A的,忘记费用流的反向边也要加一发流量了.哎,我注定是要爆零. 正睿round_3 日 ...

  6. 日常笔记3关于bool类型数组初始化的问题

    一般会有两种考虑,全为true或全为false 赋值方式: <1>memset(boolArray,0,sizeof(Array)); 头文件:#include<cstring> ...

  7. Log-Structured Merge Tree (LSM Tree)

    一种树,适合于写多读少的场景.主要是利用了延迟更新.批量写.顺序写磁盘(磁盘sequence access比random access快). 背景 回顾数据存储的两个“极端”发展方向 加快读:加索引( ...

  8. Golang 基础语法介绍及对比(二)

    传值与传参 Golong func main() { a := fmt.Println("a = ", a) // 应该输出 "a= 3" a1 := add1 ...

  9. pgsql_pg的数据类型

    PostgreSQL 提供了丰富的数据类型.用户可以使用 CREATE TYPE 命令在数据库中创建新的数据类型.PostgreSQL 的数据类型被分为四种,分别是基本数据类型.复合数据类型.域和伪类 ...

  10. Word文字中嵌套的图片向上突出,与文字的高度不一致

    文字中嵌套的图片向上突出,与文字的高度不一致. 调整方法: 选中图片,找到Font字体设置,选中位置下拉框,选择适当项. Select the inline graphic by clicking o ...