12.nuitka打包win32gui

前言

使用pyinstaller、nuitka等打包工具打包python程序之后,会遇到各种奇奇怪怪问题,例如win32gui 就加载不了。

一、分析

1.1 用pycharm快捷键查看模块路径

在pycharm下新建一个test.py文件,内容:

import win32gui
print(win32gui)

鼠标放在win32gui这个字符串上,安装ctrl键,点击鼠标,跳转到如下路径:
*****\AppData\Local\JetBrains\PyCharmCE2020.2\python_stubs\20717174
内容如下:

# encoding: utf-8
# module win32gui
# from C:\Users\lch\AppData\Local\Programs\Python\Python38\lib\site-packages\win32\win32gui.pyd
# by generator 1.147
# no doc

# imports
from pywintypes import error


# Variables with simple values

CLR_NONE = -1

dllhandle = 1931608064

ILC_COLOR = 0
ILC_COLOR16 = 16
ILC_COLOR24 = 24
ILC_COLOR32 = 32
ILC_COLOR4 = 4
ILC_COLOR8 = 8
ILC_COLORDDB = 254
ILC_MASK = 1

ILD_BLEND = 4
ILD_BLEND25 = 2
ILD_BLEND50 = 4
ILD_FOCUS = 2
ILD_MASK = 16
ILD_NORMAL = 0
ILD_SELECTED = 4
ILD_TRANSPARENT = 1

IMAGE_BITMAP = 0
IMAGE_CURSOR = 2
IMAGE_ICON = 1

LR_CREATEDIBSECTION = 8192
LR_DEFAULTCOLOR = 0
LR_DEFAULTSIZE = 64
LR_LOADFROMFILE = 16
LR_LOADMAP3DCOLORS = 4096
LR_LOADTRANSPARENT = 32
LR_MONOCHROME = 1
LR_SHARED = 32768
LR_VGACOLOR = 128

NIF_ICON = 2
NIF_INFO = 16
NIF_MESSAGE = 1
NIF_STATE = 8
NIF_TIP = 4

NIIF_ERROR = 3

NIIF_ICON_MASK = 15

NIIF_INFO = 1
NIIF_NONE = 0
NIIF_NOSOUND = 16
NIIF_WARNING = 2

NIM_ADD = 0
NIM_DELETE = 2
NIM_MODIFY = 1
NIM_SETVERSION = 4

TPM_BOTTOMALIGN = 32
TPM_CENTERALIGN = 4
TPM_LEFTALIGN = 0
TPM_LEFTBUTTON = 0
TPM_NONOTIFY = 128
TPM_RETURNCMD = 256
TPM_RIGHTALIGN = 8
TPM_RIGHTBUTTON = 2
TPM_TOPALIGN = 0
TPM_VCENTERALIGN = 16

UNICODE = True

# functions

def AbortPath(*args, **kwargs): # real signature unknown
    pass

def AlphaBlend(*args, **kwargs): # real signature unknown
    pass

def AngleArc(*args, **kwargs): # real signature unknown
    pass

def AnimateWindow(*args, **kwargs): # real signature unknown
    pass

def AppendMenu(*args, **kwargs): # real signature unknown
    pass

def Arc(*args, **kwargs): # real signature unknown
    pass

def ArcTo(*args, **kwargs): # real signature unknown
    pass

def BeginPaint(*args, **kwargs): # real signature unknown
    pass

def BeginPath(*args, **kwargs): # real signature unknown
    pass

def BitBlt(*args, **kwargs): # real signature unknown
    pass

def BringWindowToTop(*args, **kwargs): # real signature unknown
    pass

def CallWindowProc(*args, **kwargs): # real signature unknown
    pass

def CheckMenuItem(*args, **kwargs): # real signature unknown
    pass

def CheckMenuRadioItem(*args, **kwargs): # real signature unknown
    pass

def ChildWindowFromPoint(*args, **kwargs): # real signature unknown
    pass

def ChildWindowFromPointEx(*args, **kwargs): # real signature unknown
    pass

def Chord(*args, **kwargs): # real signature unknown
    pass

def ClientToScreen(*args, **kwargs): # real signature unknown
    pass

def CloseFigure(*args, **kwargs): # real signature unknown
    pass

1.2 到site-packages目录下搜索

切换到
***\AppData\Local\Programs\Python\Python38\Lib\site-packages
目录下,“ctrl+F”输入“win32gui”
在win32目录下找到win32gui.pyd文件

1.3 验证win32gui真实路径

执行’test.py’打印结果与前面第二步指向的路径一致,win32/win32gui.pyd是我们要找到包。

二、测试

2.1 准备环境

新建main.py文件

# -*- coding: utf-8 -*-
import sys, traceback
import sys, traceback
from PyQt5.QtWidgets import QWidget,QApplication
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QWidget,QApplication

class WDTPubDispatch(QWidget,Ui_Form):
	def __init__(self, parent=None):
		super(WDTPubDispatch, self).__init__(parent=parent)
		self.setupUi(self)

		self.initUI()


	def __del__(self):
		print(self.__class__,'del')

	def initUI(self):
		# 菜单模块

		self.btnRun.clicked.connect(self.run)

	def run(self):
		# 加载数据
		txtFunc = self.txtFunc.toPlainText()
		try:
			exec(txtFunc)
		except:
			traceback.print_exc()

    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(567, 476)
        self.verticalLayout = QtWidgets.QVBoxLayout(Form)
        self.verticalLayout.setObjectName("verticalLayout")
        self.label_4 = QtWidgets.QLabel(Form)
        self.label_4.setObjectName("label_4")
        self.verticalLayout.addWidget(self.label_4)
        self.btnRun = QtWidgets.QPushButton(Form)
        self.btnRun.setObjectName("btnRun")
        self.verticalLayout.addWidget(self.btnRun)
        self.label_6 = QtWidgets.QLabel(Form)
        self.label_6.setObjectName("label_6")
        self.verticalLayout.addWidget(self.label_6)
        self.txtFunc = QtWidgets.QTextEdit(Form)
        self.txtFunc.setObjectName("txtFunc")
        self.verticalLayout.addWidget(self.txtFunc)

        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "Form"))
        self.label_4.setText(_translate("Form", "通用数据处理"))
        self.label_4.setProperty("qsslevel", _translate("Form", "subtitle"))
        self.btnRun.setText(_translate("Form", "执行"))
        self.label_6.setText(_translate("Form", "输入函数:"))
        self.txtFunc.setHtml(_translate("Form", "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:\'SimSun\'; font-size:9pt; font-weight:400; font-style:normal;\">\n"
"<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><br /></p></body></html>"))

if __name__ == '__main__':
	app = QApplication(sys.argv)
	windows = WDTPubDispatch()
	windows.show()
	app.exec_()

采用nuitka打包,带命令行调试版本:

python -m nuitka --mingw64 --standalone --show-progress --show-memory --plugin-enable=qt-plugins --plugin-enable=pylint-warnings --nofollow-import-to=numpy,jinja2,matplotlib,scipy,sqlalchemy,pandas,pygal,pyzbar,pubunit,qtunit,dataunit,Crypto  --output-dir=D:\打包结果\打包与窗口函数\ main.py

–output-dir 这个输出路径自行修改

主图两个控件,一个执行按钮,一个txt控件用于接受py程序
在txt控件中输入:

import win32gui

#下面是我自定的用到win32gui的api程序
from pubunit.windowOperate import findHwnds
hwnd = findHwnds('Chrome','百度一下')
print(hwnd)

import importlib
from pubunit.file import resourcePath
importName='win32gui'
path = resourcePath('\win32\\%s.pyd' % importName)
print(path)
import os
print( os.path.exists(path) )

api = importlib.import_module(importName, path)
print(dir(api))

第一次打包完成之后,没有其他动作,执行提示:

Traceback (most recent call last):
  File "D:\打包结果\打包与~1\MAIN~1.DIS\pubDispatch.py", line 26, in run
  File "<string>", line 1, in <module>
ModuleNotFoundError: No module named 'win32gui'

ps: "pubDispatch.py"这个是我程序构造与前面给代码不一样,我采用了三个文件来写测试代码(main.py, pubDispatch.py,UiPubDispatch.ui)

2.2 实验一

把pycharm导向的win32gui.py拷贝到打包环境下,
import win32gui是成功了,都是里面是一个空壳,调用Find***函数返回值为None。
失败!!!!

2.3 实验二

由于import win32gui 失败,考虑采用import 替代品试试:

import imp          # 替代品1
from ctype import * # 替代品2
import importlib    #替代品3

经过测试,
imp的加装方法实验失败,需要后续继续研究。

ctype可以加载,但是没有具体实验,这里就不说了,自行研究。

最终importlib可以加载win32/win32gui.pyd,如下:

path='****/win32/win32gui.pyd' #最好为 绝对路径
#检查路径是否存在
print( os.path.exists(path) ) #
api = importlib.import_module('win32gui', path)
# 打印win32gui的函数
print(dir(api))
# 使用 win32gui的函数进行进一步验证
#hwnd = api.Find****(****)
#print(hwnd)

执行成功!!!!

2.4 实验三

以上解决办法是没有办法的办法,其实应该还有更好的解决思路,可以进我q群沟通。

提示:路径问题

三.总结

工作中总是会遇到意想不到的事情发生。我最近需要用到win32gui获取窗口句柄,进行下一步程序操作。以上过程,经过迷茫到有解耗时2天。分享出来供有缘人参考。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿飞哥666

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值