当前位置: 首页 > 后端技术 > Python

py2exe打包oss2和pycryptodome失败

时间:2023-03-26 13:42:17 Python

背景:最近用python开发了一个程序,程序需要在没有安装python的电脑上运行。对比了python的打包exe工具,我选择了py2exe(py2exe没有官方更新,由第三方人员开发维护)。在使用过程中,发现py2exe打包后缺少了一些文件库,所以特地记录一下。简要说明:py2exe是一个PythonDistutils扩展,可以将Python脚本转换为无需安装Python即可运行的Windows可执行程序。这里主要介绍使用py2exe打包错误的排查思路。py2exe的使用请参考py2exe官网:http://www.py2exe.org/测试环境:系统:win10x64python3.6.3宜兰:oss2==2.8.0py2exe==0.9.3.2#下载地址:https://github.com/albertosottile/py2exe/releases#pycryptodome==3.8.2安装oss2会自动下载安装,安装后目录名为Crypto测试代码app.pyimportoss2classOSSHandler:def__init__(self):self.endpoint="endpoint"self.auth=oss2.Auth("access_key_id","access_key_secret")self.bucket=oss2.Bucket(self.auth,self.endpoint,"bucket_name")defiterator(self):"""遍历bucket文件:return:"""forobject_infoinoss2.ObjectIterator(bucket=self.bucket):print(object_info.key)defmain():OSSHandler().iterator()if__name__=="__main__":main()打包代码setup.py,注意:console需要使用terminal运行,否则会通过importpy2exefromdistutils.coreimportsetuppy2exe_options={"dist_dir":"dist","compressed":1,"optimize":2,"ascii":0,}setup(name='oss',version='0.1.0',descriptionn="wintool",options={'py2exe':py2exe_options},#注意:控制台需要用终端运行,否则会闪过去console=[{#windows=[{"script":"app.py",}],zipfile="lib/shared.lib",data_files=[],)打包命令pythonsetup.pypy2exe报错运行dist文件夹app.exe报错,发现模块无法找到回溯(最近调用最后一次):文件“app.py”,第1行,在importoss2文件“”,第971行,在_find_and_load文件“”,第955行,在_find_and_load_unlocked文件“”,第656行,在_load_unlocked文件“”,第626行,在_load_backward_compatible文件“oss2\__init__.pyc”,第3行,在文件“>”,第971行,在_find_and_load文件“”,第955行,在_find_and_load_unlocked文件“”,第656行,在_load_unlocked文件“<冻结importlib._bootstrap>”,第626行,在_load_backward_compatible文件“oss2\models.pyc”,第10行,在文件“”,第971行,在_find_and_load文件“”",第955行,在_find_and_load_unlocked文件“”中,第656行,在_load_unlocked文件“”中,第626行,在_load_backward_compatible文件“oss2\utils.pyc”中,第30行,在文件“”,第971行,在_find_and_load文件“”,第955行,在_find_and_load_unlocked文件“”,第656行,在_load_unlocked文件“”,第626行,在_load_backward_compatible文件“Crypto\Cipher\__init__.pyc”中,第27行,在文件“”中,第971行,在_find_and_load文件“”,第955行,在_find_and_load_unlocked文件“”中,第656行,在_load_unlocked文件“”中,第626行,在_load_backward_compatible文件“Crypto\Cipher\_mode_ecb.pyc”中,第47行,在文件“Crypto\Util\_raw_api.pyc”中,第300行,在load_pycryptodome_raw_libOSError中:无法加载本机模块“Crypto.Cipher._raw_ecb”:尝试“_raw_ecb.cp36-win_amd64.pyd”:[WinError126]找不到指定的模块,正在尝试“_raw_ecb.pyd”:[WinError126]找不到指定的模块。查看distlibshared.lib文件,使用解压工具解压,发现py2exe工具没有打包*.pyd文件,导致模块查找失败。根据上面的报错信息,可以看到模块调用文件的位置是“CryptoUtil_raw_api.pyc”,第300行try:filename=basename+ext#通过调试发现pycryptodome_filename函数找不到*.pyd,导致错误returnload_lib(pycryptodome_filename(dir_comps,filename),cdecl)exceptOSErrorasexp:attempts.append("Trying'%s':%s"%(filename,str(exp)))参见pycryptodome_filename函数CryptoUtil_file_system。pyutil_lib,_=os.path.split(os.path.abspath(__file__))root_lib=os.path.join(util_lib,"..")#添加打印信息,查看模块加载位置print("root_lib:",root_lib)returnos.path.join(root_lib,*dir_comps)添加打印信息,查看模块加载位置,发现目录在shared.lib下,但是.pyd并没有打包进去,所以让程序载入.pyd。root_lib:D:\code\dist\lib\shared.lib\Crypto\Util\..修改*.pyd加载目录,让root_lib加载目录distlib,注意:此方法会影响解压后的oss正常使用和pycryptodome#util_lib,_=os.path.split(os.path.abspath(__file__))#root_lib=os.path.join(util_lib,"..")util_lib=os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))root_lib=os.path.join(util_lib,"Crypto")returnos.path.join(root_lib,*dir_comps)repack,将Crypto文件夹复制到distlib,Libsite-packagesCrypto文件夹只需要保留*.pyd文件即可,其他删除即可。发现并没有报模块无法加载,而是*.json文件无法加载。参考上述方法,修改libsite-packagesaliyunsdkcoreutils_init_.py文件#base_dir=os.path.dirname(os.path.abspath(aliyunsdkcore.__file__))path.dirname(os.path.abspath(aliyunsdkcore.__file__))))复制libsite-packagesaliyunsdkcoredata到distlib,运行最终目录后程序可能正常运行。通过以上思路,当打包py2exe时无法加载文件时,可以使用控制台方式找到加载的文件目录,并进行相应的修改。