近年来“自动编程”、“智能编程”方面的项目层出不穷,例如 AutoML、kite,以及最近风靡一时的 python_autocomplete,这些项目有一个共同点,就是基于机器学习模型,致力于提升代码补全和自动生成水平。
不过今天要展示的自动编程与上述概念不同,这次我们不讲学术、不论实用,抱着娱乐的心态体验一把另类的“全自动编程”模式。
转载来源
公众号:菜鸟学 Python
01.
项目介绍
今天要介绍的这个库的名字叫 pynput,与人工智能无关,这是一个控制和监控计算机输入设备的库,这是他的 GitHub 地址(详细见文末),从库的简介中可以看到,目前仅支持鼠标和键盘两种基本的输入设备。
接下来我们打开文档,看看 pynput 究竟有哪些功能。从文档目录(下图)来看,关于 pynput 的说明大体分为三个部分:分别是鼠标事件、键盘事件和平台限制。
先来简单说一下平台限制,因为事关外部输入设备,在不同的操作系统中肯定会有一些差异和功能限制,例如 Linux 下需要设置环境变量 $ DISPLAY、MAC 操作系统限制了对键盘的监控、Windows 中进程间的虚拟事件传递可能受限等等。
总的来说,平台限制并不影响基本的使用(特别是在 Windows 系统中),我们暂且放下不谈。
接着我们重点聊一聊鼠标事件和键盘事件。先来说鼠标事件部分,pynput 对鼠标事件的处理主要分为控制和监控两大部分。
在鼠标控制部分,可以通过代码模拟鼠标的移动、单击、双击、滚轮等操作,下面这张图就是文档中的演示代码,函数名称和实际事件名基本一致,很容易理解。
在鼠标事件的监控部分,监控任务 Listener 实际上是一个 threading.Thread 对象,采用回调函数的方式实时监控鼠标行为(下图是文档中的演示代码)。既然是 threading.Thread 对象,Listener 当然也就有阻塞和非阻塞两种模式,一般来说,如果想要监控物理鼠标的行为,使用阻塞模式比较合适,如果想要监控 pynput 的模拟鼠标操作,建议采用非阻塞模式。
再来看键盘事件部分,和鼠标事件类似,pynput 对键盘事件的处理也是分为控制和监控两大部分,函数结构和操作模式也跟鼠标事件基本相同,这里就不展示文档中的演示代码了。有一点需要注意的是,键盘操作中有一些特殊方法,比如“ctrl ”、‘“shift ”、“alt ”这类的组合键,还有 F1~FN、backspace、delete、insert 等特殊功能键,在 pynput 中都有专门的定义,在操作时可以直接使用。
02.
功能演示
介绍完基本功能,我们就写一段代码试一试 pynput 的设备控制以及监控效果,由于上文中重点介绍了关于鼠标事件的处理,这里就以键盘事件处理为例进行演示。
我们设计这样一个程序:
- 主线程:随机生成 20 个(准确地说是 19 个)小写英文字母,并用 pynput 模拟键盘输入,在第10个字母输入后附加输入一个退格键(backspace)。
- 监控线程:对键盘的按键和松开两种操作进行监控,同时在控制台输出相关信息,当遇到退格键(backspace)松开这一事件时,终止监控线程。
为了便于观察,在每个随机字符串输入后加入一个 0.5s 的时间间隔,另外由于这里是要监控虚拟的键盘按键事件,因此监控线程使用非阻塞模式,代码如下:
一起来看下这段代码的动态执行情况,在下面这段动画中字符(包括退格键)的输入全部都是基于 pynput 自动实现的。
(动态图,盯着看几秒哦)
通过上面这个动画可以看到,在程序运行的前半部分,输入结果和监控结果是完全一致的,直到退格键(backspace)事件发生后,控制台就不再输出监控信息,这是因为监控线程已经被终止掉了,但是模拟键盘输入仍然会继续,直到指定数量的字符串全部输入完毕为止。通过这个例子应该就能很好地理解 pynput 的监控线程了,有兴趣的朋友不妨自己体会一下。
至于鼠标事件的控制、监控功能,因为和键盘事件十分类似,这里就不再重复演示了。另外,由于鼠标没有键盘中那么多复杂的、各式各样的功能键,从某种意义上说鼠标事件的处理要比键盘事件处理更简单一些。
03.
神奇的"自动编程"
最后,我们回到今天的主题,把鼠标事件和键盘事件的控制结合起来,实现一个“全自动编程”的功能。事实上这里实现的“自动编程”与人工智能无关,也不是传统的代码匹配补全,而是控制鼠标和键盘按照我们提前设置好的步骤自动运行。
为了方便,我们就用最简单的 “Hello World” 来进行演示,在 sublime 中完成 “Hello World” 程序大概需要经过以下几个步骤:新建一个 sublime 文件 —— 命名、保存为 py 文件 —— 在新建的 py 文件中输入 “print ('Hello World')” 语句 —— 再次保存 —— 运行新的程序。
前文讲到过,pynput 可以模拟所有的鼠标和键盘操作,上面步骤中的操作自然也可以由 pynput 模拟完成,就跟手动操作一样。我们把以上操作全部写到脚本中,同时加入鼠标和键盘的监控线程,在脚本启动后不仅会自动编写运行 “Hello World” 程序,还会对鼠标和键盘的模拟操作进行实时监控,并将相关信息输出到控制台。
先来看结果,下面这个动画就是我们写的“自动编程”脚本的运行情况,整个过程全部自动执行,没有任何手动干预。
(动态图,盯着看几秒哦)
在整个过程中,所有的鼠标和键盘事件都会被监控线程记录,包括每一次键盘按键的点击和释放、鼠标的移动和点击等。
下面我们来看看这个脚本的核心代码,可以看到,我们使用 pynput 模拟了所有与鼠标和键盘有关的操作,使用这种方法还可以编写更加复杂的程序,只需要改变 keycontroller.type 的输入内容就可以。
代码语言:javascript复制keycontroller = keyboard.Controller()
mousecontroller = mouse.Controller()
# 新建文件
keycontroller.press(keyboard.Key.ctrl_l)
keycontroller.press('n')
keycontroller.release(keyboard.Key.ctrl_l)
keycontroller.release('n')
sleep(1)
# 保存文件
keycontroller.press(keyboard.Key.ctrl_l)
keycontroller.press('s')
keycontroller.release(keyboard.Key.ctrl_l)
keycontroller.release('s')
sleep(1)
# 输入文件名称
keycontroller.type('auto{}.py'.format(random.uniform(0,99)))
sleep(1)
# 点击保存
mousecontroller.position = (0, 0)
mousecontroller.move(466, 493)
mousecontroller.press(mouse.Button.left)
mousecontroller.release(mouse.Button.left)
sleep(1)
# 输入代码
keycontroller.type("print('Hello World')")
keycontroller.press(keyboard.Key.space)
sleep(1)
# 重新保存
keycontroller.press(keyboard.Key.ctrl_l)
keycontroller.press('s')
keycontroller.release(keyboard.Key.ctrl_l)
keycontroller.release('s')
sleep(1)
# 运行新程序
keycontroller.press(keyboard.Key.ctrl_l)
keycontroller.press('b')
keycontroller.release(keyboard.Key.ctrl_l)
keycontroller.release('b')
(代码可以左右滑动)
友情提示
正如本文开头所说,使用 pynput 实现的所谓“自动编程”仅仅是一种娱乐,并没有太多实用价值。但是 pynput 对于输入设备的控制和监控在实践中倒是有可能会用得上,至于如何发挥他的作用,就要看自己的想象力了。