我有个简单的应用需求:

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. [LeetCode] 375. Guess Number Higher or Lower II 猜数字大小之二

    We are playing the Guess Game. The game is as follows: I pick a number from 1 to n. You have to gues ...

  2. [LeetCode] 72. Edit Distance 编辑距离

    Given two words word1 and word2, find the minimum number of operations required to convert word1 to  ...

  3. subprocess实用手册

    背景 python执行操作系统的命令,如python执行shell命令 subprocess模块主要用于创建子进程,并连接它们的输入.输出和错误管道,获取它们的返回状态.通俗地说就是通过这个模块,你可 ...

  4. (九)golang--标识符的命名规则

    标识符的概念: (1)各种变量.方法等命名时使用的字符序列被称为标识符: (2)凡是可以自己起名字的都可以叫标识符: 标识符的命名规则: (1)由26个英文字母大小写,0-9,_组成 (2)数字不可以 ...

  5. python面试题第一份

    阅读目录 1 Python的函数参数传递 2 Python中的元类(metaclass) 3 @staticmethod和@classmethod 4 类变量和实例变量 5 Python自省 6 字典 ...

  6. linux ,查看端口

    netstat -antlp | grep java 注:grep java是过滤所有java进程

  7. java 解决safari下载中文文件名乱码

    主要就是在响应头设置content-disposition,主要遵循 RFC 5987标准. response.setHeader("content-disposition",&q ...

  8. 直接操作DOM一定比虚拟DOM操作耗时,diff算法,key值,虚拟 DOM的定义

    直接操作DOM一定比虚拟DOM操作耗时吗? 或者一次直接DOM操作一定比一次虚拟DOM操作耗时吗? 1)虚拟DOM的本质就是一个JS对象,虚拟DOM减少了真实DOM的操作,当修改数据的时候,就是修改虚 ...

  9. 【Navicat】使用navicat执行sql 查询速度很慢解决方法

    ========================== Navicat 远程连接Mysql执行普通sql速度慢问题: 场景: navicat可以连接上 远程服务器的mysql.但是在navicat执行最 ...

  10. C# vb .NET识别读取QR二维码

    二维码比条形码具有更多优势,有些场合使用二维码比较多,比如支付.那么如何在C#,.Net平台代码里读取二维码呢?答案是使用SharpBarcode! SharpBarcode是C#快速高效.准确的条形 ...