背景:因为这边PC客户端会针对特定用户展示一些优惠活动的入口,所以就导致部分用户在安装特定版本的客户端后没展示活动入口,而开发要拿到特定日志才能进行分析为什么不展示入口,这里就涉及到一个问题就是需要客户在自己PC端进行一个特定手动的操作(比如在打开客户端的情况下,鼠标焦点在特定区域内长按键盘上的某个键)去对应路径下查看生成日志文件。当然,这些步骤手动操作起来也不是很复杂,但是还是需要花费时间让客户去操作,有时候也会因为一些误操作导致获取不到日志文件,故这边就想开发一个小工具,直接运行就能获取到日志信息,减少时间浪费和一些不必要的误操作。

一、前期准备

首先这里是需要实现的步骤有:

1、自动打开PC端应用----这里考虑使用的是pywinauto这个库来实现

2、鼠标能自动移动到PC应用的特定区域----这里考虑用Pyautogui 这个库来实现

3、鼠标移动到特定区域后按住键盘某个键>4s----这里也是考虑用pyautogui中的keyDown来实现(这里有个巨大的坑困扰我几天才解决,后面会讲

4、生成日志文件后就是读取对应路径下的文件展示就行----这里直接用python自带的os就能实现

5、把代码打包成exe文件,方便发送给客户直接执行----这里用到的是Pyinstaller

好,步骤都列好了,就一步一步实现:(这边先把所有代码展示下哈)

import datetime
import time
import pyautogui
from pywinauto import Application
from time import sleep
import tkinter.messagebox as msgbox
import os

def hold_f12 (hold_time):
    import time, pyautogui
    start = time.time()
    while time.time() - start < hold_time:
        pyautogui.keyDown('f12')

#获取当前屏幕分辨率
screenWidth,screenHeight = pyautogui.size()
print(screenHeight,screenWidth)
file = '日志路径'
#通过应用路径打开应用
app = Application().start(r"应用路径")
sleep(5)
#已存在日志文件则进行删除
if os.path.exists(file):
        os.remove(file)
        print('已删除原有文件')
#鼠标移动到特定区域
pyautogui.moveTo(screenWidth-100,screenHeight-200)
sleep(1)
pyautogui.doubleClick()
#调用长按按键函数
hold_f12(5)
#释放按键
pyautogui.keyUp('f12')
sleep(1)
#存在文件及打开,不存在就报错
if os.path.exists(file):
   os.startfile(file)
else:
    msgbox.showwarning('操作提示','该文件不存在,请重新获取日志文件')

看代码是很简单的对吧,都没几行😂😂,但是中间还是遇到了一些坑,当然大神的话就轻喷了,我只是一只小菜鸡

二、介绍下里面用到的一些库的功能吧:

pywinauto

==Pywinauto==是基于Python开发的,用于自动化测试的脚本模块,主要操作于Windows标准图形界面。它可以允许你很容易的发送鼠标、键盘动作给Windows的对话框和控件

1、安装方式:

命令行安装:pip install pywinauto,简单,方便,直接。


手动安装:【解压缩后执行 python setup.py install】


pyWin32:python调用windows api的库。https://sourceforge.net/projects/pywin32/files/pywin32/Build%20220/

comtypes: COM接口的调度。https://github.com/enthought/comtypes/releases

six:用来兼容Python2和Python3的库。https://pypi.org/project/six/

Pillow:可选,用来做屏幕截图的。https://pypi.org/project/Pillow/2.7.0/

Pywinauto:PC端自动化工具。https://github.com/pywinauto/pywinauto/releases

检查安装成功:使用python解释器运行以下代码,启动windows自带的记事本,如果正常启动不报错,则安装成功。

from pywinauto.application import Application

app = Application(backend="uia").start("notepad.exe")

开发一个小工具遇到的坑_日志文件

启动start(self, cmd_line, timeout=app_start_timeout),timeout为超时参数,默认为5s,如果启动时间较长可设置 timeout。
举例:app = Application().start(r"应用路径")


pyautogui

安装参考

1、使用pip进行安装,pip install pyautogui

在我这台机器上未能成功安装

2、下载后安装

网址: https://pypi.org/project/PyAutoGUI

点Download files,下载右侧的PyAutoGUI-0.9.38.tar.gz

开发一个小工具遇到的坑_python_02

解压后,进入解压目录执行python setup.py install

按照这个方法,在我电脑上安装成功


3、检测安装是否成功

进入Python,执行:

import pyautogui

开发一个小工具遇到的坑_日志文件_03

功能介绍

pyautogui.typewrite('Hello world!') # 输入Hello world!字符串

pyautogui.typewrite('Hello world!', interval=0.25)

# 每次输入间隔0.25秒,输入Hello world!

pyautogui.press('enter') # 按下并松开(轻敲)回车键

pyautogui.press(['left', 'left', 'left', 'left']) # 按下并松开(轻敲)四下左方向键

pyautogui.keyDown('shift') # 按下`shift`键

pyautogui.keyUp('shift') # 松开`shift`键

pyautogui.keyDown('shift')

pyautogui.press('4')

pyautogui.keyUp('shift') # 输出 $ 符号的按键



pyautogui.hotkey('ctrl', 'v')

# 组合按键(Ctrl+V),粘贴功能,按下并松开'ctrl'和'v'按键



键盘键字符串 含义

'a','b','c','A','C','1','2','3', 单个字符的键

'!','@','#'等

'enter' 回车

‘esc' ESC键

'shiftleft','shiftright' 左右Shift键

'altleft','altright' 左右Alt键

'ctrlleft','ctrlright' 左右Ctrl键

‘tab'(or '\t') Tab键

'backspace','delete' Backspace键和Delete键

'pageup','pagedown' Page Up 和Page Down键

'home','end' Home键和End键

'up','down','left','right' 上下左右箭头键

'f1','f2','f3'等 F1至F12键

'volumemute','volumeup',volumedown' 静音,放大音量和减小音量键

'pause' 暂停键

'capslock','numlock','scrolllock' Caps Lock,Num Lock和 Scroll Lock键

'insert' Insert键

'printscreen' Prtsc或Print Screen键

'winleft','winright' 左右Win键(在windows上)

'command' Command键(在OS X上)

'option' Option键(在OS X上)

这里面用到的有:

pyautogui.moveTo(screenWidth-100,screenHeight-200)

这个就是根据坐标来进行移动的操作了,我这边为了适应不同尺寸的笔记本屏幕,给的就不是绝对坐标了,因为移动的鼠标位置靠近屏幕的右下角区域,故这边先获取到屏幕的尺寸(screenWidth,screenHeight),然后通过获取到的尺寸减去X轴和Y轴的一部分坐标,那么得到的坐标差不多就是我需要移动到的区域里面了

三、介绍天坑

pyautogui.keyDown( )和pyautogui.keyUp( )(按住和松开某个键)

注意!!!大坑来了哈!!!

我这边要获取日志的重要一歩操作是按住键盘“F12”保持4s已上,那么我应该怎么操作呢,大家会不会和我一样的操作,就是直接:

pyautogui.keyDown(“f12” )

sleep(5)

pyautogui.keyUp( “f12”)

是不是这样就OK了?是的,我开始确实这样写的,但是,但是,但是。。。不行

我一开始以为是没正确按住F12导致的,所以我尝试单独传F5是有一个刷新动作的

结果是刷新动作正常完成,所以可以肯定的是按住F12这个动作没错,那么应该就是这个长按大于4s这个动作没完成造成的,然后我就在网上搜呀搜,搜呀搜,看到了一片如下的文章

(原文链接:https://www.cnpython.com/qa/1153140):

不知道如何详细说明,但我使用的是pyautogui,我似乎不能让它按住键。我用这个简单的小代码,我用NohBoard来查看按键,它显示为按下一个键,但是程序输出到的任何东西,比如一个文本文档,都显示为一个输入,而不是保持

这是我的程序

from pyautogui import*
from time import sleep
time = 10
sleep(10)
print("pressing w for ", time, " seconds")
keyDown("w")
sleep(time)
keyUp("w")

print只是用于控制台输出,所以我知道它实际上在做一些事情。 我不知道为什么这不起作用

热心网友的回复:

你需要等待而不是睡觉。。。要等待,需要导入时间模块。据我所知,睡眠会暂停你当前的线程。由于线程处于挂起状态,因此无法按住“w”键。这对我有用

from pyautogui import *
import time
time_to_wait = 10

keyDown("w")
recorded_time = time.monotonic()
wait = True

while wait:
    current_time = time.monotonic()
    if current_time - recorded_time > time_to_wait:
        keyUp("w")
        wait = False


OMG,看到这篇文章我恍然大悟,醍醐灌顶,瞬间如神灵附体,原来我一直认为sleep这个写法绝对没错的,按住等待嘛,然后到时间就释放按键,多合理是吧!可是大神说这个需要的是等待而不是“睡觉”,选择sleep这个会暂停你的线程,将该线程挂起,所以导致我虽然执行了按F12,但是其实只是按一下又释放了,所以我的日志文件就是生成不了,逃不出sleep的魔抓。。。而被无限的困在梦魇中。后面特地搜了下关于sleep和wait两个的区别,文章是这样说的(原文地址:http://www.zzvips.com/article/188307.html):

(1)这两个方法来自不同的类分别是Thread和Object

(2)最主要是sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。

(3)wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用

(4)sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常

哎,花了我好几天时间终于是搞定了,期间还换过不同的库去实现点击F12的操作的,真的是走弯路。。。

四、打包搞定

好了,后面就是打包了,这个打包没啥坑,就是大家选择Pyinstaller打包时有时候打完的包会很大,这是因为打包时会把python的一些非该工具必要的包打进来,导致很大,所以按照网上搜索的方法,可以使用pipenv创建虚拟的python环境,然后在虚拟环境中重新安装该工具所需的库,然后在虚拟环境中打包就可以了,具体步骤可参照原文(链接:https://www.bbsmax.com/A/l1dyDWD05e/

  • 在命令行(CMD)使用pip命令安装pipenv库,用于创建虚拟环境

pip install pipenv

  • 新建一个准备当环境的文件夹,并cd进入该文件夹
  • 建立虚拟环境

pipenv install

  • 进入虚拟环境(以下操作皆为虚拟环境下的操作)

pipenv shell

  • 安装.py文件用到的模块

pip install 【.py用到的模块】

  • 安装pyinstaller模块,用于打包.py文件

pip install pyinstaller

  • 使用pyinstaller打包文件

pyinstaller -F E:\\pipenvtest\\test.py(.py文件根据实际情况更改)