我有个简单的应用需求:

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. 复杂模拟 | 1014 模拟K个同时到来的人在N个窗口,每个窗口只能站M个人的银行排队

    这题我以为还是之前银行排队的思路,但是做着做着就做不下去了了.看了答案我才理解到底是什么个思路. 是这样的:不同于之前排队的题,这里的K个人是同时到来的.所以首先应该让K个人的前N*M(也就是黄线内的 ...

  2. [LeetCode] 438. Find All Anagrams in a String 找出字符串中所有的变位词

    Given a string s and a non-empty string p, find all the start indices of p's anagrams in s. Strings ...

  3. oracle--表空间故障

    一,错误问题描述 ERROR: ORA: cannot identify - see DBWR trace file ORA: data : '/u01/oracle/TEST/oratmp01/te ...

  4. Spring事务调用类自己方法失效解决办法和原因

    问题 正常情况下,我们都是在controller里调用service里的方法,这个方法如果需要加事务,就在方法上加上@Transactional,这样是没问题的,事务会生效. 可是如果像下面这样,绕以 ...

  5. 代码实现一个蛇形led走马灯

    什么叫走马灯? 走马灯又叫流水灯,灯不断的走动,像流水一样,动态显示. makecode图形化编程见:http://bbs.kittenbot.cn/forum.php?mod=viewthread& ...

  6. C# 1.0 新特性之异步委托(AP、APM)

    Ø  前言 C# 异步委托也是属于异步编程中的一种,可以称为 Asynchronous Programming(异步编程)或者 Asynchronous Programming Model(异步编程模 ...

  7. python__系统 : 线程池

    参考文档: https://www.jianshu.com/p/b9b3d66aa0be 使用  ThreadPoolExecutor  类,  as_completed 是迭代器, 如果有任务执行完 ...

  8. scrapy Crawl_spider

    命令行输入:scrapy genspider --list 可以看到scrapy给我们提供的爬虫模板: basiccrawlcsvfeedxmlfeed 一般都是用默认模板生成的spider,如果需要 ...

  9. Python range() 函数用法及字符串下标

    range() 函数用法 range() 函数可创建一个整数列表,一般用在 for 循环中 range() 函数的表示方法: range(start, stop[, step]) start: 计数从 ...

  10. SpringBoot 打包成war

    1.修改pom.xml文件 <packaging>war</packaging> <properties> <project.build.sourceEnco ...