Python打包EXE方法汇总整理 | 您所在的位置:网站首页 › python形成exe › Python打包EXE方法汇总整理 |
description: 使用py2exe,pyinstaller,cx_Freeze,nuitka对python文件进行打包,尝试进行混淆代码。“乔治是世界上最后一只平塔岛象龟,而我是世界上最后一个源家后裔,最后一只平塔岛象龟应该为了种族不灭努力地繁殖后代,最后一个源家后裔应该重振家族在黑道中的威望,但是乔治只是想回自己的水坑里去打滚,而我只是想去天体海滩上卖防晒油。”源稚生盯着恺撒的眼睛,“我就是这种人,其实蛇岐八家的黑道事业和秘党的使命对我来说都不重要,我的人生理想就是去卖防晒油。我跟你叔叔不是一种人。” Python作为解释型语言,发布即公开源码,虽然是提倡开源但是有些时候就是忍不住想打包成exe,不仅仅是为了对代码进行加密,而是为了跨平台。防止有些没有安装py环境的电脑无法运行软件。 目前对python代码打包成exe的方式有5种,py2exe,pyinstaller,cx_Freeze,nuitka以及Pyarmor,分别对以上5种方法介绍,欢迎纠错和提供新的办法。 py2exe介绍py2exe是一个将python脚本转换成windows上的可独立执行的可执行程序(*.exe)的工具,这样,你就可以不用装python而在windows系统上运行这个可执行程序。 优点:可以把python打包成exe缺点:打包好的 exe只能在相同的系统下运行,比如你在XP系统用py2exe打包好的exe只能在XP上运行,在win7上肯定有问题,而且也是存在在别的XP机子上也可能不能运行,因为一些别的机子可能会缺少dll文件什么的,作者我当时之所以抛弃py2exe 也是因为这个原因;打包的文件也需要打包同exe下的dll,和一些库的压缩包,不然exe根本跑不起来打包时候报始终报RuntimeError: BeginUpdateResource错误,就需要拷贝dll文件。C:\WINDOWS\system32\python27.dll复制到dist目录总之毛病一大堆,基本上已经舍弃了使用下载安装 安装好后,准备进行打包准备一个文件x.py,这个x.py就是想要打包成exe。然后这x.py同目录下新建一个setup.py内容如下: #coding=utf-8 from distutils.core import setup import py2exe includes = ["encodings", "encodings.*"] #要包含的其它库文件 options = {"py2exe": { "compressed": 1, #压缩 "optimize": 2, "ascii": 1, "includes": includes, "bundle_files": 1 #所有文件打包成一个exe文件 } } setup ( options = options, zipfile=None, #不生成library.zip文件 console=[{"script": "x.py", "icon_resources": [(1, "Q.ico")] }]#源文件,程序图标 ) 然后这cmd窗口下运行:python setup.py py2exepyinstaller介绍PyInstaller除了win32平台外还支持Linux,Unix平台.py2exe的用法在前面的博文里已经有了,现在看看PyInstaller,pyinstaller是目前应用最多的python打包工具,也是我最常用的。 PyInstaller本身并不是Python模块,所以安装时随便放在哪儿都行。 优点:可将python文件转成可执行文件跨平台输出的可以是单一目录,也可以是一个单独的打好包的可执行文件。py2exe貌似输出目录。智能支持python的第三方模块如PyQt,外部数据文件等支持EGG格式文件可执行文件可以用UPX压缩,二进制压缩方式支持控制台和视窗两种方式。可以选择exe文件的图标 (Windows only)支持 COM server (Windows only)缺点:import导入的问题pyinstaller是很智能的,只要指定了入口py文件,那么它就会根据代码自动查找需要导入的包。但是隐式导入的话,平常运行是没有问题的,举例: # test1.py from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker DB_CONNECT_STRING = 'mysql+pymysql://root:123456@localhost/study' engine = create_engine(DB_CONNECT_STRING, echo = False) DB_Session = sessionmaker(bind = engine) session = DB_Session() print('this is my test')运行这个ORM库的初始化引擎,是没有问题的,在console得到结果: this is my test那么我们开始打包,使用最简单的pyinstaller test1.py。打包完成后,在当前目录下有个dist文件夹,进入dist下的test1文件夹,然后打开cmd,运行这个exe,我们就会发现: 提示: no model named 'pymysql'这是怎么回事呢?那么问题来了,sqlalchemy这个库在初始化的时候是不需要显示导入引擎库的,它自己有一个create_engine()的函数来初始化,这个字符串是使用者根据规则来自己填写的。其实解决的方法很简单,我们只要在显式导入pymysql这个库即可。现在我们导入这个库: import pymysql重新打包一遍(重新打包的时候记得删除掉spec文件,否则会有缓存,或者是加上--clean选项清除掉),再次运行,现在就没有这个问题了。 多进程打包的问题官方的CPython存在一个GIL锁,这个锁的存在有很多优点,很多库都是线程安全的,单线程执行的效率也高。在python早期的一个版本中取消掉了GIL,代之以高粒度的锁来实现多线程,但是实际应用中单个线程的效率大大降低。故后来又将GIL这个锁还原回去,所以至今的python2也好还是python3中都会有这个锁。但是这个锁有很大一个问题,那就是效率问题,它导致了python仅仅只能利用一个core来进行数据的计算。所以后面为了弥补这个GIL带来的问题,专家们设计了multiprocessing库,gevent库等。前一个是多进程库,为了解决python用于数据密集型处理的情况;后一个用于异步IO处理的情况,基本原理就是在CPU时钟之间来回切换,简单的例子就是爬虫程序爬取网页的时候。假如有10个url,我们都要去GET它,实际上网络之间的延迟是大大高于计算机内部的,那么这个时间内计算机就切换到下一个。 有时候运用多进程是必须的,这个替代不了,哪怕它占用资源很多。 使用首先安装一般情况下: pip install pyinstaller但是会爆错误,比如命令行下出现 UnicodeDecodeError: 'gbk' codec can't decode pyinstaller等等这个时候下载pyinstall按转包文件解压后,放在没有中文的目录下,输入 python setup.py install即可完成 首先写一个main.py的文件,到网上下载一个图标,保存为logo.ico使用方法(例子)在: pyinstaller -D -p F:\Python27\Lib -i logo.ico mian.py -D:打包成多个文件 -p:指定python安装包路径 -i:指定图标,到网上下载一个图标,保存为logi.ico文件, mian.py:要打包的文件 注意main.py与logo.ico必须放在同一个目录下 -D与-F一一对应,-F是打包成一个单独的文件。 最后一排加上--noconsole,就是无窗口运行。运行完命令行即可生成exe文件 多进程打包如果py程序是多进程的话,使用pyinstaller打包会出现错误,这个时候只要加上一行代码 在: if __name__=='__mian__': #新增下面一行代码即可打包多进程 multiprocessing.freeze_support() word文件打包如果要打包那种操作word的文件代码,用pyinstaller工具把使用到python-docx库的脚本打包成exe可执行文件后,双击运行生成的exe文件,报错: docx.opc.exceptions.PackageNotFoundError: Package not found at 'C:\Users\ADMINI~1.PC-\AppData\Local\Temp\_MEI49~1\docx\templates\default.docx'经过在stackoverflow上搜索,发现有人遇到过类似的问题(问题链接:cx_freeze and docx - problems when freezing),经过尝试,该问题的第二个回答可以解决这个问题: I had the same problem and managed to get around it by doing the following. First, I located the default.docx file in the site-packages. Then, I copied it in the same directory as my .py file. I also start the .docx file with Document() which has a docx=... flag, to which I assigned the value: os.path.join(os.getcwd(), 'default.docx') and now it looks like doc = Document(docx=os.path.join(os.getcwd(), 'default.docx')). The final step was to include the file in the freezing process. Et voilà! So far I have no problem.大概的解决步骤是这样的: 找到python-docx包安装路径下的一个名为default.docx的文件,我是通过everything这个强大的搜索工具全局搜索找到这个文件的,它在我本地所在的路径是: E:\code\env\.env\Lib\site-packages\docx\templates把找到的default.docx文件复制到我的py脚本文件所在的目录下。修改脚本中创建Document对象的方式:从原来的创建方式: document = Document()修改为: import os document = Document(docx=os.path.join(os.getcwd(), 'default.docx'))再次用pyinstaller工具打包脚本为exe文件 把default.docx文件复制到与生成的exe文件相同的路径下,再次运行exe文件,顺利运行通过,没有再出现之前的报错,问题得到解决。 其他事项有的时候你打包图标的时候会报错,会显示logo error之类的,这是因为图标里面的格式出错了,需要用图片编辑软件重新对图片内部大小进行设置,这个百度一下吧~ 如果要加密混淆代码(其实没有用,一样可以反编译出你的源代码,但是聊胜于无吧) 加上一行 --key=asfweakjhfksafkasdkdbas随便几个字符串 好像要安装依赖包,根据提示安装即可 cx_Freeze介绍也是一种打包软件,介于py2exe和pyinstaller之间。 优点python中比较常用的python转exe方法有三种,分别是cx_freeze,py2exe,PyInstaller。py2exe恐怕是三者里面知名度最高的一个,但是同时相对来说它的打包质量恐怕也是最差的一个。pyinstaller打包很好,但是操作工序较为复杂,推荐cx_freeze,可以通过pip install cx-freeze 安装 缺点只能指定一个要打包的模块,也就是启动模块发布后,可执行文件执行路径不能有中文(最好也不要有空格)启动执行的文件中不要有下面这种判断,否则可执行文件执行会没有任何效果if __name__=='__mian__':将exe放到其他机子上运行,弹出“找不到msvcr100.dll“ ,手动将”msvcr100.dll“拷贝到dist目录下即可要去掉exe里的后面黑色控制台窗口就在前面的命令改成:cxfreeze C:\Users\restartRemote.py (需打包文件路径) –target-dir D:\pyproject (存放exe的目标文件夹路径)–base-name=win32gui使用安装方法: 打开cmd,输入pip install cx-freeze 后,会发现在python的Scripts文件夹下生成了三个文件然后在cmd中,切换到Scripts路径下,输入 python cxfreeze-postinstall,会发现Scripts文件夹下又多了.bat文件,此时已经安装成功继续在cmd下尝试输入 cxfeeeze -h 验证下,显示成功。提示:直接通过 pip install cx-freeze 安装,仍然出现错误时(找不到文件),最好去官网:网址手动下载相应版本的cx-freeze文件,放在Scripts文件夹下,手动双击安装,然后再运行cxfreeze-postinstall。(例如:我的python版本是3.4.3,下载cx_Freeze-4.3.3.win-amd64-py3.4的文件。注意,版本不对无法安装!) 在cxfreeze的安装目录下即\Python34\Scripts,添加一个文件cxfreeze.bat(可用记事本)cxfreeze.bat内容如下: @ echo off C:\Python34\python.exe C:\Python34\Scripts\cxfreeze %*在该目录下输入czfreeze -h也可以查看安装情况(用pip install cxfreeze就可直接安装改第三方库) 打包方法 打包文件时要在Scripts文件夹路径下操作,文件的路径最好是绝对路径。例如:将 G 盘的 hello.py 打包到 G 盘的 123文件夹下:cxfreeze g:\hello.py --taget-dir g:\123 或者 cxfreeze g:\hello.py --taget-dir g:\123 --base-name=Win32GUI。加上--base-name=Win32GUI可以在运行exe时去掉cmd黑框。 具体操作: 首先在命令提示符中使用cd命令转换到所需要转换的python文件的目录中,因为转换后的dist文件夹会出现在命令提示符的当前目录中 然后输入: cxfreeze --init-script=C:\Users\tangc\Desktop\alien_invasion\alien_invasion.py alien_invasion.py --init-script=后接绝对路径如果你的程序中有图片等资源,是需要根据程序中的相对路径加入到dist文件中,也要在.exe同目录中加入images的文件夹(图片资源) 如果原.py程序使用了图片等素材,并且添加图片是相对路径(同一个文件夹下可以不使用绝对路径),打包文件后,需要将图片等素材拷贝一份放在打包后的文件夹下,否则运行.exe程序会找不到图片素材。 如果原.py程序使用图片添加的是绝对路径,在本地电脑上运行时可能不会发现错误。但是你将打包后的文件发给另一台机器,运行.exe程序会报错,大概意思是“根据你写的绝对路径找不到图片等素材”,即使你在文件夹下拷贝了素材,但是绝对路径也是错误的,所以,最好使用上一种方法。 nuitkaNuitka直接将python转换成C++代码 ,再编译C++代码产生可执行文件,完全不存在反向解析的问题,非常安全,而且由于可执行文件由C++编译而来,运行速度也会获得提升。 当有一些大型的代码写完后,为了防止反编译源代码,我会使用nuitka进行打包,但是他存在一个很明显的缺点,那就是在另一台电脑上无法运行…并且实际编译时需要近20分钟,编译的时候cpu持续100% 不过如果只是自己的电脑上运行的话,还是挺好使的 注意nuitka对python的某些语法有专门要注意的地方 也可以通过pip下载,安装完nuitka后 再下载地址的中选择相对的版本号,下载py解释器,这里你可以理解成使用niutka改造后的cpython解释器 然后安装下载相对于版本号的msi文件即可 下载完后会提示安装编译c++代码的软件,使用的是gcc,下载地址是mingw 64 选择操作系统 我直接下载的shimingw-w64,你可以点击这里直接下载 下载后安装 选项如下 等待安装即可 安装好有会有一个MinGW64的文件夹,比如我要打包一个back.py的文件,把这个py文件放在MinGW64目录下,下面是我实验出来的一些经验打包命令行 python -m nuitka --recurse-all --standalone cc.py python -m nuitka --standalone back.py # 上面两种是可以用的打包方式 python -m nuitka --recurse-all --recurse-plugins=F:\Python27\Lib --remove-output --plugin-enable=enum_compat back.py # 带图标并且有窗口 python -m nuitka --recurse-all --recurse-plugins=F:\Python27\Lib --remove-output --icon=logo.ico --plugin-enable=enum_compat back.py # 不带窗口不带图标 python -m nuitka --recurse-all --recurse-plugins=F:\Python27\Lib --remove-output --plugin-enable=enum_compat --windows-disable-console back.py # 不删除辅助文件夹 python -m nuitka --recurse-all --recurse-plugins=F:\Python27\Lib --icon=logo.ico --plugin-enable=enum_compat back.py # 其他可运行 python -m nuitka --recurse-all --recurse-plugins=F:\Python27\Lib --standalone --remove-output --icon=logo.ico --plugin-enable=enum_compat back.py上面那几条是我去年的时候总结的,使用的是python2,在使用py3更新后,图标需要指定位置 C:\Program Files\mingw-w64\x86_64-8.1.0-win32-seh-rt_v6-rev0>python3 -m nuitka --recurse-all --windows-icon=logo.ico --standalone main.py具体的变动使用 python3 -m nuitka -h即可查看使用说明 在编译的时候大概要挺长时间,并且cpu持续暴涨,之前使用锐龙5 1400编译一个程序大概是15分钟,换上9900k后大概一分钟左右就好了。 速度确实快了一些 虚拟环境打包本机的电脑中python包比较杂乱,而且2和3版本混淆在一起,使用pyinstaller打包的时候想用3的环境但是又默认使用2,而且电脑上的pyinstaller安装其他插件都是2版本的,这种情况下就很糟心,并且有些包是完全不需要不依赖的,这个时候就显得很臃肿,所以使用pipenv安装py3的相关环境,在flask学习过程中,提起到pipenv,虚拟包管理软件进行软件打包处理,具体介绍 前提:python目录下的script目录添加到环境变量 首先到py3的script目录下,安装pipenv(如果之前安装了pipenv也不要紧) pyton3 pip3.6.exe install pipenv然后创建一段代码,用来打包,随便写一段代码好了 # coding:utf-8 import requests import os headers = {'User-Agent':'I AM LANGZI'} r = requests.get(url='http://www.langzi.fun',headers=headers) print('状态码:'+str(r.status_code)) print('-**-*-*-*-*-*-*-*-**-*') print(r.content) os.system('pause')这段代码随便取名为a.py 然后创建一个文件夹,为了方便记住,就取名python2exe文件夹,这个文件夹专门用来将py代码打包成exe,把上面的a.py保存到python2exe文件夹下面。 打开cmd,输入pipenv,这个时候我的电脑报错了,提示 UnicodeDecodeError: 'utf-8' codec can't decode byte 0xce in position 4: in....因为windows默认gbk编码,这个时候要修改源码将utf-8改成gbk就能解决,如果你有其他好的方法欢迎交流。 修改方法 在的C:\python3\Lib\site-packages\pipenv\vendor\shellingham的nt.py中78行,修改成 info = {'executable': str(pe.szExeFile.decode('gbk'))}然后输入命令检测pipenv是否能成功运行 pipenv check此时报错: File "c:\python3\lib\site-packages\pipenv\vendor\pythonfinder\_vendor\pep514tools\_registry.py", line 75, in __getattr __ raise AttributeError(attr) AttributeError: version当前目录下会生成pipfile文件,但是内容为空 通过查看pipenv官方文档,需要指定一下虚拟环境的配置信息,编辑pipfile,修改内容为 [[source]] url = "https://pypi.tuna.tsinghua.edu.cn/simple" verify_ssl = true name = "pypi" [dev-packages] [packages] requests = "*" [requires] python_version = "3.6" # 这里指定用生成的3.6版本然后继续输入 pipenv check返回结果: C:\python2exe>pipenv check Checking PEP 508 requirements… Passed! Checking installed package safety… All good!到此为止pipenv安装成功 这个时候这个文件夹里面就生成了python3.6的独立虚拟环境,这个时候激活虚拟环境 pipenv shell然后查看一下当前的虚拟环境信息 pipenv --where # 显示虚拟环境所在目录 pipenv --venv # 显示虚拟环境信息 pipenv --py # 显示python虚拟环境解释器的信息因为是新建的虚拟环境,所以里面没有任何外部包,就需要先安装,举个例子先安装requests这个包,再python2exe目录下启动cmd,输入 pipenv install requests # 还能指定版本,比如pipenv install requests==20.00然后查看刚刚安装的包和依赖 pipenv graph如果要删除就 pipenv uninstall requests # 想要删除所有的外部包就输入 pipenv uninstall --all要在虚拟环境里安装好你py文件中调用的库,不然打包出来也没法正常运行。 最后安装pyinstaller pipenv install pyinstaller这个时候我的电脑报错: [pipenv.exceptions.InstallError]: ['Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple', 'Collecting pyinstall er==3.4 (from -r C:\\Users\\浪子\\AppData\\Local\\Temp\\pipenv-u8g559jn-requirements\\pipenv-209rryi9-requirement.txt (l ine 1))', ' Using cached https://pypi.tuna.tsinghua.edu.cn/packages/03/32/0e0de593f129bf1d1e77eed562496d154ef4460fd5cec fd78612ef39a0cc/PyInstaller-3.4.tar.gz', ' Installing build dependencies: started', " Installing build dependencies: f inished with status 'done'", ' Getting requirements to build wheel: started', " Getting requirements to build wheel: f inished with status 'error'", ' Complete output from command c:\\users\\浪子\\.virtualenvs\\python2exe-lqrqjwd-\\script s\\python3.exe c:\\users\\浪子\\.virtualenvs\\python2exe-lqrqjwd-\\lib\\site-packages\\pip\\_vendor\\pep517\\_in_process .py get_requires_for_build_wheel C:\\Users\\浪子\\AppData\\Local\\Temp\\tmprp_w934y:', ' Failed to import the site modu le', ' Traceback (most recent call last):', ' File "c:\\users\\浪子\\.virtualenvs\\python2exe-lqrqjwd-\\lib\\site.py ", line 791, in ', ' main()', ' File "c:\\users\\浪子\\.virtualenvs\\python2exe-lqrqjwd-\\lib\\site.py", line 781, in main', ' execsitecustomize()', ' File "c:\\users\\浪子\\.virtualenvs\\python2exe-lqrqjwd-\\lib\\si te.py", line 553, in execsitecustomize', ' import sitecustomize', ' File "C:\\Users\\浪子\\AppData\\Local\\Temp\ \pip-build-env-qfpa92l1\\site\\sitecustomize.py", line 7', " SyntaxError: (unicode error) 'utf-8' codec can't decode by te 0xc0 in position 0: invalid start byte", ' ', ' ----------------------------------------'] [pipenv.exceptions.InstallError]: ['Command "c:\\users\\浪子\\.virtualenvs\\python2exe-lqrqjwd-\\scripts\\python3.exe c: \\users\\浪子\\.virtualenvs\\python2exe-lqrqjwd-\\lib\\site-packages\\pip\\_vendor\\pep517\\_in_process.py get_requires_ for_build_wheel C:\\Users\\浪子\\AppData\\Local\\Temp\\tmprp_w934y" failed with error code 1 in C:\\Users\\浪子\\AppData \\Local\\Temp\\pip-install-ugo2mgu4\\pyinstaller'] ERROR: ERROR: Package installation failed... ================================ 0/1 - 00:00:05解决方法是下载pyinstaller的按转包,使用虚拟环境的解释器安装到虚拟环境, 保存到python2exe目录下 解压后,回到cmd窗口 cd PyInstaller-3.4然后安装 python install.py install这个时候即可安装成功 安装好了后启动打包文件即可 pyinstaller -F a.py这个时候会报错 2260 WARNING: lib not found: api-ms-win-crt-stdio-l1-1-0.dll dependency of c:\users\langzi\.virtualenvs\python2exe-lqrqjwd-\scripts\python3.exe 2424 WARNING: lib not found: api-ms-win-crt-math-l1-1-0.dll dependency of c:\users\langzi\.virtualenvs\python2exe-lqrqjwd-\scripts\python3.exe 2588 WARNING: lib not found: api-ms-win-crt-runtime-l1-1-0.dll dependency of c:\users\langzi\.virtualenvs\python2exe-lqrqjwd-\scripts\python3.exe 2753 WARNING: lib not found: api-ms-win-crt-heap-l1-1-0.dll dependency of c:\users\langzi\.virtualenvs\python2exe-lqrqjwd-\scripts\python3.exe 2917 WARNING: lib not found: api-ms-win-crt-locale-l1-1-0.dll dependency of c:\users\langzi\.virtualenvs\python2exe-lqrqjwd-\scripts\python3.exe 3153 WARNING: lib not found: api-ms-win-crt-stdio-l1-1-0.dll dependency of c:\users\langzi\.virtualenvs\python2exe-lqrqjwd-\scripts\python36.dll 3317 WARNING: lib not found: api-ms-win-crt-math-l1-1-0.dll dependency of c:\users\langzi\.virtualenvs\python2exe-lqrqjwd-\scripts\python36.dll 3481 WARNING: lib not found: api-ms-win-crt-conio-l1-1-0.dll dependency of c:\users\langzi\.virtualenvs\python2exe-lqrqjwd-\scripts\python36.dll 3647 WARNING: lib not found: api-ms-win-crt-runtime-l1-1-0.dll dependency of c:\users\langzi\.virtualenvs\python2exe-lqrqjwd-\scripts\python36.dll 3810 WARNING: lib not found: api-ms-win-crt-time-l1-1-0.dll dependency of c:\users\langzi\.virtualenvs\python2exe-lqrqjwd-\scripts\python36.dll 3975 WARNING: lib not found: api-ms-win-crt-heap-l1-1-0.dll dependency of c:\users\langzi\.virtualenvs\python2exe-lqrqjwd-\scripts\python36.dll 4138 WARNING: lib not found: api-ms-win-crt-convert-l1-1-0.dll dependency of c:\users\langzi\.virtualenvs\python2exe-lqrqjwd-\scripts\python36.dll 4304 WARNING: lib not found: api-ms-win-crt-filesystem-l1-1-0.dll dependency of c:\users\langzi\.virtualenvs\python2exe-lqrqjwd-\scripts\python36.dll 4473 WARNING: lib not found: api-ms-win-crt-process-l1-1-0.dll dependency of c:\users\langzi\.virtualenvs\python2exe-lqrqjwd-\scripts\python36.dll 4639 WARNING: lib not found: api-ms-win-crt-locale-l1-1-0.dll dependency of c:\users\langzi\.virtualenvs\python2exe-lqrqjwd-\scripts\python36.dll 4806 WARNING: lib not found: api-ms-win-crt-environment-l1-1-0.dll dependency of c:\users\langzi\.virtualenvs\python2exe-lqrqjwd-\scripts\python36.dll 4975 WARNING: lib not found: api-ms-win-crt-string-l1-1-0.dll dependency of c:\users\langzi\.virtualenvs\python2exe-lqrqjwd-\scripts\python36.dll 5143 WARNING: lib not found: api-ms-win-crt-stdio-l1-1-0.dll dependency of C:\Windows\system32\vcruntime140.dll 5306 WARNING: lib not found: api-ms-win-crt-runtime-l1-1-0.dll dependency of C:\Windows\system32\vcruntime140.dll 5471 WARNING: lib not found: api-ms-win-crt-heap-l1-1-0.dll dependency of C:\Windows\system32\vcruntime140.dll 5635 WARNING: lib not found: api-ms-win-crt-convert-l1-1-0.dll dependency of C:\Windows\system32\vcruntime140.dll 5801 WARNING: lib not found: api-ms-win-crt-string-l1-1-0.dll dependency of C:\Windows\system32\vcruntime140.dll这个时候需要安装vc++库 然后修改生成下spec的文件pathex片段 在其中的pathex字段中,添加api-ms-win-crt-*-1-0.dll的文件路径。通常如果安装了VC++运行库的话,其地址为“C:\Program Files\Windows Kits\10\Redist\ucrt\DLLs\x86”(32位操作系统)或“C:\Program Files (x86)\Windows Kits\10\Redist\ucrt\DLLs\x86”(64位操作系统)。此处选用的是VC++的32位版本库文件。 比如: # -*- mode: python -*- block_cipher = None a = Analysis(['a.py'], pathex=['C:\\python2exe','C:\Program Files (x86)\Windows Kits\10\Redist\ucrt\DLLs\x86'], binaries=[], datas=[], hiddenimports=[], hookspath=[], runtime_hooks=[], excludes=[], win_no_prefer_redirects=False, win_private_assemblies=False, cipher=block_cipher, noarchive=False) pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher) exe = EXE(pyz, a.scripts, a.binaries, a.zipfiles, a.datas, [], name='a', debug=False, bootloader_ignore_signals=False, strip=False, upx=True, runtime_tmpdir=None, console=True )然后输入: pyinstaller a.spec就能生成exe文件了。 代码混淆在线版你可以自己写混淆器,虽然说是防君子不防小人,但是…..罢了不提了….. 我使用的是一个在线的代码混淆器,猜测代码会上传到那个服务器上面,所以用或不用看你的需求了 注意:代码规范符合python3 PyarmorPyarmor 是一个导入和运行加密 Python 脚本的命令行工具。他支持命令行操纵加密与图形化界面操作。 下载安装当然首先要安装 pip3 install pyarmor命令行操作使用命令行高级命令 单个文件加密打包首先加密脚本使用 obfuscate 命令,加密 src 目录下面的所有 .py 文件 pyarmor obfuscate src/hello.py运行加密脚本,会在目录下生成一个dist文件夹,文件夹里面就是加密后的脚本代码 像运行正常脚本一样运行加密后的脚本 hello.py cd ./dist/ python hello.py打包加密脚本使用 pack 命令,把脚本加密之后直接生成可以单独运行的可执行文件 pyarmor pack src/hello.py生成不同许可文件 首先使用命令 hdinfo 查看目标机器的硬件设备信息 然后使用命令 licenses, 创建新的许可文件 接着使用新生成的许可文件替换默认许可文件 dist/license.lic 最后再次运行加密脚本 queens.py,测试一下新的许可证 pyarmor hdinfo pyarmor licenses \ --expired "2018-12-31" \ --bind-disk "100304PBN2081SF3NJ5T" \ --bind-mac "70:f1:a1:23:f0:94" \ --bind-ipv4 "202.10.2.52" \ customer-jondy cp licenses/customer-jondy/license.lic ./dist/ cd ./dist/ python hello.py封装成exe虽然加密脚本可以无缝替换原来的脚本,但是打包的时候还是存在一个问题: 加密之后所有的依赖包无法自动获取 解决这个问题的基本思路是 使用没有加密的脚本找到所有的依赖文件使用加密脚本替换原来的脚本添加加密脚本需要的运行辅助文件到安装包替换主脚本,因为主脚本会被编译成为可执行文件运行 pyarmor pack 命令进行打包的时候, PyArmor 会进行如下的工作 第一步是加密所有的脚本,保存到 dist/obf: pyarmor obfuscate --output dist/obf hello.py第二步是生成 .spec 文件,这是 PyInstaller 需要的,把加密脚本需要的 运行辅助文件也添加到里面: pyinstaller --add-data dist/obf/license.lic --add-data dist/obf/pytransform.key --add-data dist/obf/_pytransform.* hello.py dist/obf/hello.py第三步是修改 hello.spec, 在 Analysis 之后插入下面的语句,主要作用是 打包的时候使用加密后的脚本,而不是原来的脚本: a.scripts[-1] = 'hello', 'dist/obf/hello.py', 'PYSOURCE' for i in range(len(a.pure)): if a.pure[i][1].startswith(a.pathex[0]): x = a.pure[i][1].replace(a.pathex[0], os.path.abspath('dist/obf')) if os.path.exists(x): a.pure[i] = a.pure[i][0], x, a.pure[i][2]最后运行这个修改过的文件,生成最终的安装包: pyinstaller hello.spec检查一下安装包中的脚本是否已经加密: # It works dist/hello/hello.exe rm dist/hello/license.lic # It should not work dist/hello/hello.exe 加密包(Package)从这个例子中,可以学习到 如何加密一个 Python 包 mypkg,它所在的路径是 examples/testpkg如何设置加密包的运行期限如何使用外部脚本 main.py 来导入和使用加密后 mypkg 包中的函数如何发布加密后的包给用户使用如下命令: cd /path/to/pyarmor # 使用 obfuscate 去加密包,加密后的脚本存放在 `dist/mypkg` pyarmor obfuscate --output=dist/mypkg examples/testpkg/mypkg/__init__.py # 使用命令 licenses 生成一个有效期到 2019-01-01 的授权文件 pyarmor licenses --expired 2019-01-01 mypkg2018 # 使用新的授权文件覆盖默认的授权文件 cp licenses/mypkg2018/license.lic dist/mypkg # 使用第三方脚本 `main.py` 导入加密库 cd dist cp ../examples/testpkg/main.py ./ python main.py # 打包整个路径 `mypkg`,发布给客户 zip -r mypkg-obf.zip mypkg zip 命令是linux下的打包命令,win下直接压缩包即可 使用 Project 来管理和加密脚本从这个例子中,可以学习到 如何使用 Project 管理加密脚本如何绑定加密脚本到硬盘、网卡等如何跨平台发布加密脚本如何为不同客户定制授权认证文件这是一个更接近真实场景的例子,加密后的脚本 queens.py 会以不同的授权方 式发布给不同的客户: John: 运行在 64位 Ubuntu 上面,2019年5月5号过期,之后就无法在使用Lily: 运行在一台 64位 Win10 上面,这台机器的硬盘序列号必须是 100304PBN2081SF3NJ5TTom: 运行在一台嵌入式设备 Raspberry Pi 上面,网卡Mac地址必须是 70:f1:a1:23:f0:94,并且2019年5月5号过期使用命令如下: cd /path/to/pyarmor # 使用命令 init 创建一个工程 pyarmor init --src=examples/simple --entry=queens.py projects/simple # 切换到新创建的工程 cd projects/simple # 这儿自动生成有一个脚本 `pyarmor`,在 Windows 下面名字是 `pyarmor.bat` # 使用命令 `build` 加密工程中所有的 `.py` 文件,加密脚本存放在 `dist` 下面 pyarmor build # 生成不同的授权文件 # # 为 John 生成的限时许可,新的许可文件存放在 "licenses/john/license.lic" pyarmor licenses --expired 2019-03-05 john # 为 Lily 生成的硬盘许可,新的许可文件存放在 "licenses/lily/license.lic" pyarmor licenses --bind-disk '100304PBN2081SF3NJ5T' lily # 为 Tom 生成的限时和网卡绑定许可,新的许可文件存放在 "licenses/tom/license.lic" pyarmor licenses --bind-mac '70:f1:a1:23:f0:94' --expired 2019-03-05 tom # 创建给 John 的发布包 # mkdir -p customers/john # 复制所有的加密脚本到新目录 cp -a dist/ customers/john # 替换默认的许可文件 cp licenses/john/license.lic customers/john/dist # 替换平台相关的动态链接库,从网站上下载适用 64位 Linux 的版本 rm -f customer/john/dist/_pytransform.* wget http://pyarmor.dashingsoft.com/downloads/platforms/linux_x86_64/_pytransform.so -O customer/john/dist/_pytransform.so # 打包在路径 `customer/john/dist` 的所有文件,发布给 John # 对于 Lily 和 Tom 来说,基本操作都是一样,除了动态链接库需要根据不同的平台分别下载和替换 # wget http://pyarmor.dashingsoft.com/downloads/platforms/win_amd64/_pytransform.dll wget http://pyarmor.dashingsoft.com/downloads/platforms/raspberrypi/_pytransform.so 打包加密脚本从这个例子中,可以学习到 如何使用命令 pack 来打包加密的脚本 PyArmor 需要使用第三方的打包工具,推荐工具是 PyInstaller, 首先安装 pip install pyinstaller接着就可以运行命令 pack 打包加密脚本 cd /path/to/pyarmor pyarmor pack examples/py2exe/hello.py运行一下打包好的可执行文件 dist/hello/hello确认脚本已经加密 rm dist/hello/license.lic dist/hello/hello使用其他工具需要先写一个安装脚本setup.py, 这儿有一个 py2exe 的实 例 examples/py2exe/setup.py。这个脚本用来打 包主脚本hello.py 和另外一个模块 queens.py。 首先安装 py2exe,并确定没有加密之前能够正常打包 pip install py2exe cd /path/to/pyarmor cd example/py2exe python setup.py py2exe # 输出文件在这里 ls dist/之后运行命令 pack 来打包加密脚本 pyarmor pack --type py2exe hello.py检查一下输出路径 dist,发现多个几个文件,这些是运行加密脚本需要的辅助 文件,另外 library.zip 也被修改了,里面的 queens.pyc 被替换成为了加 密后的脚本 对于其他打包工具 cx_Freeze, py2app, 基本使用方法和 py2exe 很类似。 图形化操作下载可以通过 pip3 install pyarmor或者你也可以单独下载: 解压下载文件到任意目录,例如 /opt。本教程后面的章节都是以 /opt 作为 WebApp 的安装路径,运行里面的例子需要把它替换成为实际的安装路径。 启动可以通过命令行 pyarmor-webui还可以通过如下方式进行设置后启动 打开文件夹 /opt/pyarmor/webapp,双击 start-server.bat for Windows 或者 start-server.sh for Linux 也可以通过命令行方式启动,假定 python 的安装路径为 D:/tools/Python27 cd /opt/pyarmor/webapp D:/tools/Python27/python server.py这条命令会打开一个控制台,显示服务器的行为动态,同时本机默认的浏览器会自动打开一个网页,这就是 WebApp。 单击 项目, 进入 Pyarmor 的世界 我们下面的操作主要就是在这个网页里面进行的,另外还需要打开一个命令窗口执行相关的 Python 命令。 演示模式如果在项目页面的右上角有个 演示版本 的按钮,那就是说,WebApp 现在只能演示功能。通常情况下,有两种方式会进入演示模块 直接在文件夹打开 /opt/pyarmor/webapp/index-zh.html使用方法下面通过四个例子来演示 WebApp 的主要功能: 第一个例子最简单,运行一个加密的脚本第二个稍微复杂一些,演示如何导入加密的模块和包(Package)第三个例子主要是演示如何绑定加密脚本到指定机器最后一个例子演示如何设置加密脚本的有效期运行加密脚本 在这个例子中,将会加密 /opt/pyarmor/src/examples/queens.py,然后运行加密后的脚本。 案例 1进行单个加密 按照下图输入 标题, 源路径, 启动脚本, 输出路径点击按钮 加密加密成功之后在目录 /opt/pyarmor/webapp/build 下面会有加密脚本 queens.py 以及相关的辅助文件。 运行 在命令窗口执行里面的命令 # 进入输出目录 cd /opt/pyarmor/webapp/build # 执行包裹脚本,并且传入命令行参数: "6" python queens.py 6查看加密后的 queens.py,它的内容如下 import pyimcore __pyarmor__(__name__, b'xxxxx')最后点击按钮 保存,保存项目信息,后面的例子中还会用到这个项目。 案例 2导入加密模块 第二个例子稍微复杂一些,使用一个真实的包 /opt/pyarmor/src/examples/pybench 。这是 一个用来测试 Python 实现性能的小工具包,用在这里最合适不过了。 在这个例子中,将会加密 pybench 中的所有 ".py" 文件,然后运行脚本 pybench.py,它可以像正常方式一样,使用导入后的加密模块。 加密 点击按钮 新建,创建一个新的项目按照下图内容输入 标题, 源路径, 输出路径, http://MANIFEST.in关于 http://MANIFEST.in 的格式,参考这里 这个模板完全参照 Python Distutils 里面相应的文件,它用来列出项目中需要加密的文件。例如 include *.py recursive-include examples *.py上面的例子一看就能明白: 所有在项目 源路径 下面的 py 文件,递归所有在项目子目录 examples 下面的 py 文件。 模板支持的命令如下表所示(从 Python 帮助文件拷贝而来) Command Description --------------------------------------------------------------------------------------------------------------------------- include pat1 pat2 ... include all files matching any of the listed patterns exclude pat1 pat2 ... exclude all files matching any of the listed patterns recursive-include dir pat1 pat2 ... include all files under dir matching any of the listed patterns recursive-exclude dir pat1 pat2 ... exclude all files under dir matching any of the listed patterns global-include pat1 pat2 ... include all files anywhere in the source tree matching — & any of the listed patterns global-exclude pat1 pat2 ... exclude all files anywhere in the source tree matching — & any of the listed patterns prune dir exclude all files under dir graft dir include all files under dir需要注意的是在 Pyarmor WebApp 中,http://MANIFEST.in 里面的路径都是相对于项目 源路径,并且不支持绝对路径。 点击按钮 保存,保存修改后的项目点击按钮 加密所有加密后的脚本存放在 输出路径 /opt/pyarmor/webapp/build/pybench 下面 运行 运行加密脚本 pybench.py cd /opt/pyarmor/webapp/build/pybench python pybench.py查看加密脚本 pybench.py import pyimcore __pyarmor__(__name__, b'xxx') 案例 3绑定加密脚本到指定机器 这个例子演示如何绑定加密脚本到当前机器,在之前首先要得到本机的硬盘序列号。Pyarmor 提供了一个命令可以直接获取本机的硬盘序列号,打开一个命令行窗口,执行下面的命令 cd /opt/pyarmor/src python pyarmor.py hdinfo Harddisk's serial number is '100304PBN2081SF3NJ5T'生成许可证 我们继续使用第一个例子中的项目 Queen,加密后的脚本已经存放在 /opt/pyarmor/webapp/build,可以直接在这个例子里面使用。 点击按钮 打开,弹出项目列表对话框在列出的项目中选中 project-1:Queen,然后点击对话框下方按钮 打开如上图所示,新的许可文件会显示在 所有许可方式 的列表中,上图中例子是 Bind to 100304PBN2081SF3NJ5T (projects\project-1\license-0.lic) 小括号里面的内容是许可证的文件名称,加上安装路径,全路径的文件名称是 /opt/pyarmor/webapp/projects/project-1/license-0.lic 使用新的许可证 使用新的许可证只需要使用新的许可证替换默认许可证 /opt/pyarmor/webapp/build/license.lic 即可 cp /opt/pyarmor/webapp/projects/project-1/license-0.lic /opt/pyarmor/webapp/build/license.lic打开命令行窗口,再次运行 cd /opt/pyarmor/webapp/build python queens.py 6在本机可以正常运行,但是在其他机子上,就会出错。 设置加密脚本的有效期 这个例子演示如何设置加密脚本的有效期,我们继续上面的操作。 点击左侧 许可证选中 设置加密脚本的有效期,在下面的文本框输入 2017-12-25和上面的例子一样,新的许可文件会显示在 所有许可方式 的列表中,用新的许可文件替换旧的即可。 打开命令窗口,再次运行 cd /opt/pyarmor/webapp/build python queens.py 6这个加密脚本只能在本机运行到2071年的圣诞节。在圣诞节之后,就会出错。 所有环境打包下载为了方便迁移环境,所以将上文中的pyinstaller等打包环境下载后保存在一个压缩包里面,方便下载使用 参考链接 1 参考链接 2 参考链接 3 |
CopyRight 2018-2019 实验室设备网 版权所有 |