开一个新坑,关于pywinauto的使用的,
最近一两个星期都在踩pywinauto的坑,踩了的好多坑,时常在想要是我看教程的时候就能有人指导清楚我就好了;
网上搜到的pywinauto教程没能让我避开雷区,如果说这个教程能够帮助更多人不要踩坑可就太好了;
当然如果说现实是我踩坑多纯粹是我比较憨那我也认了,各位带哥不要嘲笑就好了。
pywinauto可以说是使用起来比较轻松简单的模块,对我这种摸鱼选手非常友善;
gayhub页面:https://github.com/pywinauto/pywinauto
文档(这个很好用,查的越多越不容易踩雷):https://pywinauto.readthedocs.io/en/latest/contents.html
作者的Stack Overflow个人页(实在遇到解决不了的问题可以提问看看):https://stackoverflow.com/users/3648361/vasily-ryabov
作者不仅仅一直在更新,甚至一直在回答问题,可谓是我这样菜鸡的希望之光
首先我安装的是python的32位,python安装就不用讲了吧,x86表示32位,x64表示64位,
官网直接下载默认为32位,64位要选Windows x86-64 executable installer这个版本;
当然我之所以选32位的还是因为目标程序的兼容性问题,最终选什么版本还是看个人需求。
直接最简单的安装:
命令行:
pip install pywinauto
如果出现提示升级pip,基本可以无视
选择特定版本的python安装/安装到指定版本的python:
E:\python_32\python -m pip install pywinauto
替换成你自己的路径便可,那些什么-t -d的方法不知道为什么我就是不行,直接给我糊到设了环境变量的那个版本里了
如果使用的IDE是pychram,那就更简单了:
直接选小加号选包就OK了
有两种方法,实例化以后才能抓到窗口内的各种控件按钮文本框之类的,也是目前来说最容易出问题的一个部分,
直接放原文:
An Application()
instance is the point of contact for all work with the application you are automating. So the Application instance needs to be connected to a process. There are two ways of doing this:
需要用到的主要函数为Application(),连接进程的方法有两种:
start(self, cmd_line, timeout=app_start_timeout) # instance method:
or:
connect(self, **kwargs) # instance method:
start()
is used when the application is not running and you need to start it. Use it in the following way:
start()
是用于程序没打开的情况的,但是一般没打开就打开就完事儿了,所以start()一般主要还是用来模拟打开的这整个过程
app = Application().start(r"c:\path\to\your\application -a -n -y --arguments")
这里已经有第一个坑了:
问题就出在这个路径这里了:
app_path = 'D:\000\msk\test_library\bin\i_cant_tell.exe'
app = Application().start(app_path)
dlg_test = app[r'测试窗体']
诡异错误: ValueError: embedded null character
使用如下语句读取名为0_xx.txt 文件时,遇到错误 ValueError: embedded null character
if __name__ == '__main__':
fr = open("F:\eclipse_workspace\machine_learning_example\Ch02\trainningDigits\0_38.txt")
for i in range(32):
lineStr = fr.readline()
lineStr = lineStr.strip()
print(lineStr)
pass
1、通过测试,确定错误确实是文件读取语句;
2、是否是文件中包含null字符呢?用ultraedit工具用16进制形式检查数据文件,没有发现有null字符;
3、是否是因为Windows中的编码和python中的编码形式不一样造成的呢?查看到文件编码为GBK格式,但python是可以正确读取GBK文件的,试了其它GBK文件,读取没有任何问题;
4、是不是因为文件名太长?把数据文件放在当前文件夹下,尝试读取确实没有问题。但真的是文件名太长的原因吗?这时候我才发现文件名中有个 ‘\0’ ,才如梦初醒。
注意:一般情况下,Python解释器会将遇到的‘\’识别为路径,会自动增加一个'\'以便和转义字符进行区分,但若遇到转义字符则不增加‘\’。
例如:上述文件名将被转换为 F:\\eclipse_workspace\\machine_learning_example\\Ch02\trainingDigits\0_38.txt。因而出错。
文件路径中若包含‘\0’、'\t' 等特殊转义字符时要特别注意。
推荐文件路径写法:
上面部分的原作者是https://www.cnblogs.com/quintin/p/7372291.html
如果喜欢用000,001,00加英文这样的路径,就很容易出这个问题
回到文档:
The timeout parameter is optional, it should only be necessary to use if the application takes a long time to start up.
如果上文中:start(self, cmd_line, timeout=app_start_timeout)你要打开的程序启动时间特别长,最好设置timeout,这里的timeout单位是秒,而且不是用来防止过长的,而是防止过短的...如果不填写,他自身带的时间非常短,很容易就timeout弹出了。
connect()
is used when the application to be automated is already launched. To specify an already running application you need to specify one of the following:
connect()是用来连接已经启动的程序的,要连接上需要标志物,可以是一下三种参数任意选择:
当有多个进程时可以加不止一个标志物。
process: (PID) |
the process id of the application, e.g. |
---|---|
handle: (句柄) |
The windows handle of a window of the application, e.g. |
path: (路径) |
The path of the executable of the process ( |
or any combination of the parameters that specify a window, these get passed to the pywinauto.findwindows.find_elements()
function. e.g.
或者用pywinauto.findwindows.find_elements()。
会用上面这个的不用往下看了,我估计一时半会儿都讲不到哪里,甚至还有太监的可能性。
这里十分不推荐path,感觉速度比较慢,容易报错,原因我还没研究过
app = Application().connect(title_re=".*Notepad", class_name="Notepad")
Note: The application has to be ready before you can use connect*(). There is no timeout or retries like there is when finding the application after start(). So if you start the application outside of pywinauto you need to either sleep or program a wait loop to wait until the application has fully started.
在使用connect()前必须要让程序准备好,尤其是那种比较复杂的程序,而start()用前最好保证程序完全关闭,在残留的情况下连接不到进程或者连接到了但是后续的操作没反应就要好好考虑下是不是连接出了问题。
其实start也是会出现一些问题,我使用的一种方法是在进程中寻找程序,有的话直接返回PID,没有的话就用cmd启动应用,这主要是解决我的软件的问题,不太清楚是权限还是什么问题,我用start会卡在登录加载界面,而用cmd加载出路径然后再启动就没问题,我也不知道为什么。
from pywinauto import Application
import psutil
import os
your_name_path = '000/msk/YOUR_NAME/YOUR_FILE'
cd_your_name_path = 'd: & cd '+your_name_path+' & start your_name.exe'
# 这里的d:是盘符,不要问我为什么写的这么怪,被逼无奈
def connect_your_name():
your_name_pid = None
for i in psutil.pids():
p = psutil.Process(i)
if str(p.name()) == 'YOUR_NAME.exe':
your_name_pid = i
elif str(p.name()) == 'your_name.exe':
your_name_pid = i
if your_name_pid is None:
os.system(cd_your_name_path)
your_name_app = connect_your_name()
else:
your_name_app = Application(backend='uia').connect(process=your_name_pid)
return your_name_app
其实我怀疑
app = Application().start(r"c:\path\to\your\application -a -n -y --arguments")
这里的参数是能够解决我的问题的,但是之前我是看别人教程尝试的,所以尝试出了这种笨办法,如果有时间我看看能不能解决这方面的问题再更新。
为什么要重点写写连接程序的问题,因为这里是最基本的地方,这里连接不好,后面所有的操作都无从谈起。
后面还要着重讲的就是Application(backend='win32')和Application(backend='uia'),这里也是坑了我好久
也不知道什么时候再写呢,说不定就太监了