文章目录
坤坤音效键盘说明:
说明一下: 对于连续按键触发的音效,不要求快速连续按下,只要连续即可。
说明一下: 为了让大家知道我按下了哪些按键,视频中将我按下的按键进行了打印。
该程序需要用到以下两个第三方库:
在命令行或终端中输入以下命令进行安装:
pip install pynput==1.6.8
pip install playsound==1.2.2
说明一下: 这里下载第三方库时最好不要下载最新版本的。
准备几个想要播放的音频,在Python程序所在目录下创建一个子目录,将这些音频文件放到这个子目录当中。比如:

说明一下: 博主的这些音频文件是在B站上找到的,大家可以去各个资源网站上下载音频文件,也可以自行录音。
监听键盘
监听键盘的步骤如下:
代码如下:
from pynput import keyboard
def onRelease(key):
print(f'用户输入: {key}')
listener = keyboard.Listener(on_release=onRelease)
listener.start()
listener.join()
此时每当按键被敲击时,listener就会自动调用我们设置的回调函数,进而打印出被敲击的按键。

说明一下:
普通键和特殊键
虽然在回调函数中通过print能够直接打印出被按下的按键,但实际这个参数并不是字符串类型的,我们不能将该参数直接与字符串进行比较,这样得不到正确的比较结果。
正确的做法如下:
但实际我们并不知道用户本次按键按下的是普通键还是特殊键,并且如果用户按下的是普通键,那么参数对象是没有name成员变量的,反之,如果用户按下的是特殊键,那么参数对象是没有char成员变量的。如果访问了不存在的成员变量,那么程序就会抛出异常AttributeError。
这时可以借助异常来进行处理:
AttributeError,但由于我们对异常AttributeError进行了捕捉,因此程序不会终止,此时执行流会跳转到except块中,执行except块中处理特殊键的代码逻辑。代码如下:
def onRelease(key):
try:
print(f'用户输入: {key.char}')
print(type(key.char)) # <class 'str'>
except AttributeError:
print(f'用户输入: {key.name}')
print(type(key.name)) # <class 'str'>
判断特殊键的另一种方式
当用户按下的是特殊键时,除了通过参数对象的name成员变量得知用户按下的是哪个按键之外,还可以通过如下方式进行比较:
# 下面两种比较方式都可以
if key.name == 'ctrl_l':
print('用户按下的是左Ctrl键')
if key == keyboard.Key.ctrl_l:
print('用户按下的是左Ctrl键')
说明一下: Key是keyboard模块中的一个枚举类,Key中枚举出了各个特殊键。
播放音频
播放音频的步骤如下:
代码如下:
from playsound import playsound
playsound('sound/j.mp3')
建立映射关系
为了能够快速获得一个字符串对应的音频路径,可以使用字典建立字符串与对应音频的映射关系。
代码如下:
# 建立字符串与对应音频的映射
letterToAudio = {
'j': 'sound/j.mp3',
'n': 'sound/n.mp3',
't': 'sound/t.mp3',
'm': 'sound/m.mp3',
'jntm': 'sound/jntm.mp3',
'ngm': 'sound/ngm.mp3',
'esc': 'sound/phw.mp3',
'ctrl_l': 'sound/xmr.mp3'
}
编写逻辑
代码逻辑的编写如下:
代码如下:
history = '' # 记录历史敲击过的字母
def onRelease(key):
global history
audio = ''
try:
print(f'用户输入: {key.char}')
# 记录敲击过的字母
if len(history) < 4:
history += key.char
else:
history = history[1:] + key.char
# 优先判断是否触发连续字母音效,再判断是否触发单字母音效
if history == 'jntm':
audio = letterToAudio[history]
elif history[-3:] == 'ngm':
audio = letterToAudio[history[-3:]]
elif key.char in 'jntm':
audio = letterToAudio[key.char]
except AttributeError:
print(f'用户输入: {key.name}')
# 按下的不是普通键,可以把history清空
history = ''
# 判断是否触发音效
if key == keyboard.Key.esc:
audio = letterToAudio['esc']
elif key == keyboard.Key.ctrl_l:
audio = letterToAudio['ctrl_l']
# 判断是否本次敲击按键是否触发音效
if audio != '':
playsound(audio)
说明一下:
'jntm',长度为4,因此history只需要记录最近4次敲击过的字母即可。'ngm'的连续音效时,history的长度可能为3,也可能为4,这时需要通过负索引的方式对history进行切片操作,保证是在用history中的后三个字母在进行判断。当前程序存在的问题
现在我们编写的代码已经可以运行了,但当前的效果体验并不好:
为了解决这个问题,我们可以在调用playsound播放音频的时候创建一个线程,让该线程去执行播放音频的动作,而让当前线程继续进行按键监听操作。
引入线程
引入线程的步骤如下:
代码如下:
# 创建线程对象,并指定其要执行的程序例程
t = Thread(target=playsound, args=(audio, ))
# 启动线程
t.start()
说明一下:
(arg, )的方式传入,这后面这个逗号是不可省略的,否则就不是元组类型了。完整代码
引入线程后的完整代码如下,此时在播放音频的时候敲键盘就不会存在卡顿现象,并且在音频播放期间能够再次触发其他音频。
from pynput import keyboard
from playsound import playsound
from threading import Thread
# 建立字符串与对应音频的映射
letterToAudio = {
'j': 'sound/j.mp3',
'n': 'sound/n.mp3',
't': 'sound/t.mp3',
'm': 'sound/m.mp3',
'jntm': 'sound/jntm.mp3',
'ngm': 'sound/ngm.mp3',
'esc': 'sound/phw.mp3',
'ctrl_l': 'sound/xmr.mp3'
}
history = '' # 记录历史敲击过的字母
def onRelease(key):
global history
audio = ''
try:
print(f'用户输入: {key.char}')
# 记录敲击过的字母
if len(history) < 4:
history += key.char
else:
history = history[1:] + key.char
# 优先判断是否触发连续字母音效,再判断是否触发单字母音效
if history == 'jntm':
audio = letterToAudio[history]
elif history[-3:] == 'ngm':
audio = letterToAudio[history[-3:]]
elif key.char in 'jntm':
audio = letterToAudio[key.char]
except AttributeError:
print(f'用户输入: {key.name}')
# 按下的不是普通键,可以把history清空
history = ''
# 判断是否触发音效
if key == keyboard.Key.esc:
audio = letterToAudio['esc']
elif key == keyboard.Key.ctrl_l:
audio = letterToAudio['ctrl_l']
# 判断是否本次敲击按键是否触发音效
if audio != '':
# 创建线程对象,并指定其要执行的程序例程
t = Thread(target=playsound, args=audio)
# 启动线程
t.start()
listener = keyboard.Listener(on_release=onRelease)
listener.start()
listener.join()
一、打包资源文件夹
当前项目播放音频时需要用到的音频文件就叫做资源文件,博主将这些资源文件放在了一个名为sound的文件夹中。如下:

二、修改KunKunKeyboard.py文件
我们需要在KunKunKeyboard.py文件中加入如下函数,该函数是用于生成资源文件的访问路径的。
# 生成资源文件访问路径
def resource_path(relative_path):
if getattr(sys, 'frozen', False): # 是否Bundle Resource
base_path = sys._MEIPASS
else:
base_path = os.path.abspath(".")
return os.path.join(base_path, relative_path)
代码中所有使用资源文件路径的地方,都需要通过调用该函数来生成资源文件的访问路径,然后再通过这个生成的路径来访问资源文件,我们只需要将字典中的内容更改一下即可。如下:
# 建立字符串与对应音频的映射
letterToAudio = {
'j': resource_path(os.path.join('sound', 'j.mp3')),
'n': resource_path(os.path.join('sound', 'n.mp3')),
't': resource_path(os.path.join('sound', 't.mp3')),
'm': resource_path(os.path.join('sound', 'm.mp3')),
'jntm': resource_path(os.path.join('sound', 'jntm.mp3')),
'ngm': resource_path(os.path.join('sound', 'ngm.mp3')),
'esc': resource_path(os.path.join('sound', 'phw.mp3')),
'ctrl_l': resource_path(os.path.join('sound', 'xmr.mp3'))
}
说明一下: join是os.path模块中的一个函数,它的作用是将多个路径进行拼接。
三、准备图标文件
如果你想要修改生成的exe程序的图标的话,那么你需要准备一个
32
×
32
32\times32
32×32像素的图片文件,图片文件需要为ico格式,可以使用百度的JPG在线转ICO:https://www.aconvert.com/cn/icon/jpg-to-ico/

将生成的图标文件KunKunKeyboard.py的同级目录下。如下:

三、生成KunKunKeyboard.spec文件并修改
在命令行或终端中输入以下命令,生成KunKunKeyboard.spec文件:
pyi-makespec -F -i logo.ico KunKunKeyboard.py
此时在KunKunKeyboard.py的同级目录下会生成一个KunKunKeyboard.spec文件。如下:

此时,打开KunKunKeyboard.spec文件,并将做如下修改:

说明一下:
datas=[]。四、生成exe程序
最后在命令行或终端中输入以下命令:
pyinstaller KunKunKeyboard.spec
此时在KunKunKeyboard.py的同级目录下会生成一个dict目录,生成的exe程序就在该目录中。如下:

拓展内容(非必须)
如果在修改KunKunKeyboard.spec时,同时将console的值设置为False。如下:

那么此时生成的exe程序在运行时将不会弹出窗口,程序运行后也不会在任务栏显示。需要注意的是,如果要这样做,需要将程序中两处调用print函数的地方注释掉,因为此时没有窗口供print输出,如果print被调用那么程序将会抛异常。
此时要终止这个程序有以下几种方法:
说明一下: 代码中没有考虑小键盘中的数字按键和小数点按键,当这些按键被按下时会抛出没有被捕获到的异常,可以将这些按键当作暂停键。
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
我正在尝试在Ruby中制作一个cli应用程序,它接受一个给定的数组,然后将其显示为一个列表,我可以使用箭头键浏览它。我觉得我已经在Ruby中看到一个库已经这样做了,但我记不起它的名字了。我正在尝试对soundcloud2000中的代码进行逆向工程做类似的事情,但他的代码与SoundcloudAPI的使用紧密耦合。我知道cursesgem,我正在考虑更抽象的东西。广告有没有人见过可以做到这一点的库或一些概念证明的Ruby代码可以做到这一点? 最佳答案 我不知道这是否是您正在寻找的,但也许您可以使用我的想法。由于我没有关于您要完成的工作
我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden
这个问题在这里已经有了答案:关闭10年前。PossibleDuplicate:Pythonconditionalassignmentoperator对于这样一个简单的问题表示歉意,但是谷歌搜索||=并不是很有帮助;)Python中是否有与Ruby和Perl中的||=语句等效的语句?例如:foo="hey"foo||="what"#assignfooifit'sundefined#fooisstill"hey"bar||="yeah"#baris"yeah"另外,类似这样的东西的通用术语是什么?条件分配是我的第一个猜测,但Wikipediapage跟我想的不太一样。
什么是ruby的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht
华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o
我想解析一个已经存在的.mid文件,改变它的乐器,例如从“acousticgrandpiano”到“violin”,然后将它保存回去或作为另一个.mid文件。根据我在文档中看到的内容,该乐器通过program_change或patch_change指令进行了更改,但我找不到任何在已经存在的MIDI文件中执行此操作的库.他们似乎都只支持从头开始创建的MIDI文件。 最佳答案 MIDIpackage会为您完成此操作,但具体方法取决于midi文件的原始内容。一个MIDI文件由一个或多个音轨组成,每个音轨是十六个channel中任何一个上的
C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.
本文主要介绍在使用Selenium进行自动化测试或者任务时,对于使用了iframe的页面,如何定位iframe中的元素文章目录场景描述解决方案具体代码场景描述当我们在使用Selenium进行自动化测试的时候,可能会遇到一些界面或者窗体是使用HTML的iframe标签进行承载的。对于iframe中的标签,如果直接查找是无法找到的,会抛出没有找到元素的异常。比如近在咫尺的例子就是,CSDN的登录窗体就是使用的iframe,大家可以尝试通过F12开发者模式查看到的tag_name,class_name,id或者xpath来定位中的页面元素,会抛出NoSuchElementException异常。解决
MIMO技术的优缺点优点通过下面三个增益来总体概括:阵列增益。阵列增益是指由于接收机通过对接收信号的相干合并而活得的平均SNR的提高。在发射机不知道信道信息的情况下,MIMO系统可以获得的阵列增益与接收天线数成正比复用增益。在采用空间复用方案的MIMO系统中,可以获得复用增益,即信道容量成倍增加。信道容量的增加与min(Nt,Nr)成正比分集增益。在采用空间分集方案的MIMO系统中,可以获得分集增益,即可靠性性能的改善。分集增益用独立衰落支路数来描述,即分集指数。在使用了空时编码的MIMO系统中,由于接收天线或发射天线之间的间距较远,可认为它们各自的大尺度衰落是相互独立的,因此分布式MIMO