目录
一、打包
1、pyinstall打包
代码编写完成,如何在没有python环境的电脑上运行?编写了一个GUI程序,如何把文件打包好,发给别人直接使用?其实最简单的办法就是把.py源文件,打包成可执行程序员exe文件,别人直接双击exe文件就可以运行了。
python实现打包exe有很多方案,主要有py2exe、cxfreeze、PyInstaller三种,py2exe和cxfreeze的安装过程比较麻烦,且对高版本python支持不好,虽然pyinstaller打包后文件相对较大,但是其安装的简单性和易用性得到广大Python使用者的青睐,今天就介绍pyinstaller的使用。
安装
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pyinstaller
或
pip install pyinstaller
常用参数
-h 查看帮助
-w 忽略控制台,打包gui软件时使用
-F dist目录中只生成一个exe文件
-p 表示你自己定义需要加载的类库的路径
-D 创建dist目录,里面包含exe以及其他一些依赖性文件(默认,可不添加)
-i 指定打包程序使用的图标文件
命令使用:
使用cmd进入到项目文件夹,执行如下命令:
pyinstaller -i ico.png -F -w demo.py
两种打包方式
1. 文件夹模式onedir
默认方式,使用命令:pyinstaller fileren.py
执行完命令后,在项目文件夹下多出了三个文件,build,dist和fileren.spec、pycache。
- build文件夹用于存储日志文件。
- dist文件夹储存可执行文件即相关依赖。
- __pycache__文件夹里是Python版本信息。
- fileren.spec打包的配置文件,可以配置依赖资源。
除了dist文件夹,其它都可以删除,没什么用。
这种模式下,需要把整个dist文件夹发给别人才能运行。
2.单文件模式onefile
加上-F参数,全部的依赖文件都会被打包到exe文件中,在dist文件夹中只有一个可执行文件,
把这个可执行文件发给别人就可以直接运行了。
pyinstaller -w -F fileren.py
默认的应用图标,有点丑,可以自己找一个好看点的图标。然后加上-i参数,重新打包:
pyinstaller -F -w -i folder.ico fileren.py
pyd方式加密
为什么要使用pyd:
pyd文件类似于DLL, 一般用C/C++语言编译而成, 可用作模块导入Python程序中。
pyd文件仅适用于特定版本的Python, 不同版本间互不兼容, 如Python3.8不支持3.7版本的文件。
pyd文件用C/C++语言编译而成, 难以被反编译, 在保护Python程序源码上有很好的效果。
而且由于使用了C/C++等低级语言, 代码执行效率较高。
pyd是动态链接库文件, 本质上与dll文件相同, 安全性比pyc文件高很多. 所以这种方式不算真正意义上的加密, 而是一个编译过程.
操作如下:
安装easycython模块:
pip install easycython
使用easycython命令将py转pyd:
easycython xx.py
会在同一目录生成xx.pyd(如果是64位系统生成的文件名为xx.cp36-win_amd64.pyd);
将xx.cp36-win_amd64.pyd重命名为xx.pyd
使用pyinstaller打包(由于xx.py和xx.pyd在同一目录, pyinstaller会优先打包pyd), 打包时添加—hidden-import xx选项.
生成的打包文件中会包含xx.pyd;
2、Nuitka打包
Nuitka的打包类似于pyinstaller,但是程序运行性能更高,错误率更高,打包效率更低。可以酌情选择。
Nuitka安装命令:
pip install nuitka
只封装一个python文件:
python -m nuitka --lto=no yourpythonfile.py
会生成一个bin文件和其他文件,使用./yourpythonfile.bin就和python yourpythonfile.py的效果是一样的。
完整使用命令
nuitka --mingw64 --windows-disable-console --standalone --show-progress --show-memory --plugin-enable=qt-plugins --plugin-enable=pylint-warnings --recurse-all --recurse-not-to=numpy,jinja2,matplotlib,scipy,sqlalchemy,pandas,pygal,pyzbar,win32com --output-dir=out main.py
封装所有模块
python -m nuitka --follow-imports program.py
如果包含一些动态库,无法直接通过PYTHONPATH环境变量设置后直接导入的话,可以在封装过程中指定路径
python -m nuitka --follow-imports --include-plugin-directory=plugin_dir program.py
封装动态库
如果想将某些模块封装成动态库,需要使用--module
指令
python -m nuitka --module some_module.py
运行后会生成some_module.so
动态库,可以被其他程序导入使用。注意这个生成的动态库只能被相同版本的CPython导入。
封装包
封装整个包,同时一些模块使用动态库的方式,可以使用下面的命令
python -m nuitka --module some_package --include-package=some_package
如果要将代码分发到其他系统中,可以通过指定--standalone
来生成一个文件夹,默认会导入所有模块,如果要排除一些模块,可以使用--nofollow-inport-to
指令,但是在程序运行时可能会出现ImportError
python -m nuitka --standalone program.py
封装过程
封装的时候,.py文件首先是被转成了.c文件,然后被编译成了.o文件,最后合并成.bin可执行文件。
从bin到C是不可逆的,从C到Python也是不可逆的,代码相对来说很安全。
还有编译成动态链接库的方法,在这里不赘述了,主要是编译成.so文件,安全性也是高的。反汇编.so的时候,C代码也不是原来的代码了,无法推回Python
二、终端输出带颜色的文字
方式一、通过ANSI转义码实现
前言:当你在Python中使用print函数输出文本时,可能会想要以不同的颜色呈现文本。这可以通过使用ANSI转义码来实现。ANSI转义码是一种用于在终端上控制文本显示的特殊字符序列。下面是一个简单的例子,演示如何使用ANSI转义码在Python中以不同的颜色输出文本:
# 输出红色文本
print("\033[91mHello, world!\033[0m")
# 输出绿色文本
print("\033[92mHello, world!\033[0m")
# 输出黄色文本
print("\033[93mHello, world!\033[0m")
# 输出蓝色文本
print("\033[94mHello, world!\033[0m")
# 输出紫色文本
print("\033[95mHello, world!\033[0m")
# 输出青色文本
print("\033[96mHello, world!\033[0m")
在这个例子中,我们使用了ANSI转义码来设置文本的颜色。\033
是ANSI转义码的起始字符,后面跟着一个方括号和一个数字序列。这个数字序列表示颜色代码。在这个例子中,我们使用了数字序列91到96来设置文本的颜色,分别对应红色、绿色、黄色、蓝色、紫色和青色。在每个输出语句的结尾处,我们使用\033[0m
来恢复默认的文本颜色。
除了颜色之外,ANSI转义码还可以用于设置文本的背景色、加粗、下划线等等。以下是一些常见的ANSI转义码:
转义码 | 描述 |
---|---|
\033[0m | 关闭所有属性 |
\033[1m | 设置高亮单独 |
\033[2m | 设置一半亮度 |
\033[3m | 斜体 |
\033[4m | 下划线 |
\033[5m | 闪烁 |
\033[7m | 反显 |
\033[8m | 消隐 |
\033[30m | 设置前景色为黑色 |
\033[31m | 设置前景色为红色 |
\033[32m | 设置前景色为绿色 |
\033[33m | 设置前景色为黄色 |
\033[34m | 设置前景色为蓝色 |
\033[35m | 设置前景色为紫色 |
\033[36m | 设置前景色为青色 |
\033[37m | 设置前景色为白色 |
\033[40m | 设置背景色为黑色 |
\033[41m | 设置背景色为红色 |
\033[42m | 设置背景色为绿色 |
\033[43m | 设置背景色为黄色 |
\033[44m | 设置背景色为蓝色 |
\033[45m | 设置背景色为紫色 |
\033[46m | 设置背景色为青色 |
\033[47m | 设置背景色为白色 |
下面是一个使用ANSI转义码的例子,演示如何以不同的颜色和样式输出文本:
# 输出带有颜色和样式的文本
print("\033[1m\033[31mHello, world!\033[0m")
print("\033[1m\033[32mHello, world!\033[0m")
print("\033[1m\033[33mHello, world!\033[0m")
print("\033[1m\033[34mHello, world!\033[0m")
print("\033[1m\033[35mHello, world!\033[0m")
print("\033[1m\033[36mHello, world!\033[0m")
print("\033[1m\033[37mHello, world!\033[0m")
# 输出带有背景色的文本
print("\033[1m\033[41mHello, world!\033[0m")
print("\033[1m\033[42mHello, world!\033[0m")
print("\033[1m\033[43mHello, world!\033[0m")
print("\033[1m\033[44mHello, world!\033[0m")
print("\033[1m\033[45mHello, world!\033[0m")
print("\033[1m\033[46mHello, world!\033[0m")
print("\033[1m\033[47mHello, world!\033[0m")
# 输出带有下划线的文本
print("\033[4mHello, world!\033[0m")
在这个例子中,我们使用了ANSI转义码来设置文本的样式和颜色。例如,\033[1m
表示设置高亮度,\033[31m
表示设置前景色为红色。我们还可以组合不同的ANSI转义码来实现更多的效果,例如\033[1m\033[31m
表示设置高亮度和前景色为红色。
需要注意的是,ANSI转义码只在支持ANSI的终端中有效。如果你的终端不支持ANSI转义码,那么输出的文本可能会出现乱码或者其他奇怪的效果。另外,ANSI转义码也可能会在不同的终端中产生不同的效果,因此在使用ANSI转义码时需要谨慎。
2.示例
代码如下(示例):
print('\033[0;30m欢迎使用学生选课系统\033[0m')
print('\033[1;31m欢迎使用学生选课系统\033[0m')
print('\033[4;32m欢迎使用学生选课系统\033[0m')
print('\033[5;33m欢迎使用学生选课系统\033[0m')
print('\033[7;34m欢迎使用学生选课系统\033[0m')
print('\033[8;35m欢迎使用学生选课系统\033[0m')
print('\033[1;36m欢迎使用学生选课系统\033[0m')
print('\033[1;37m欢迎使用学生选课系统\033[0m\n')
可以看到,只需要将需要改变颜色的字符串写在\033[1;37m
和\033[0m\n
中间就可以了,\033[1;37m
主要是用来确定输出格式,\033[0m
主要是用来结束这个格式的输出,如果没有加后面这段,如果后面还有不需要改变颜色的字符串输出,也会因为没有加这个结束标志而变的和前面的特殊字符串一样了,就起不到区分效果了。
print('\033[1;31;40m欢迎使用学生选课系统\033[0m')
print('\033[1;31;41m欢迎使用学生选课系统\033[0m')
print('\033[1;31;42m欢迎使用学生选课系统\033[0m')
print('\033[1;31;43m欢迎使用学生选课系统\033[0m')
print('\033[1;31;44m欢迎使用学生选课系统\033[0m')
print('\033[1;31;45m欢迎使用学生选课系统\033[0m')
print('\033[1;31;46m欢迎使用学生选课系统\033[0m')
print('\033[1;31;47m欢迎使用学生选课系统\033[0m')
这个是加了高亮后的效果图,个人感觉还是不加高亮的看着舒服一点。
方式二、使用termcolor
库
准备工作
首先,我们需要安装 termcolor
库。打开终端,输入以下命令来安装:
pip install termcolor
文字颜色输出
要在终端输出彩色文字,我们可以使用 termcolor 库中的 colored 方法。该方法需要传入两个参数:要输出的文字以及文字颜色。
下面是一个简单的示例:
from termcolor import colored
print(colored('Hello, World!', 'red'))
执行上述代码,会在终端中输出红色的“Hello, World!”字样。
除了红色,还有很多种颜色可以选择,包括但不限于:
- 黑色(‘grey’)
- 红色(‘red’)
- 绿色(‘green’)
- 黄色(‘yellow’)
- 蓝色(‘blue’)
- 紫色(‘magenta’)
- 青色(‘cyan’)
- 白色(‘white’)
我们不妨再来一个示例,输出绿色的“Success!”字样:
from termcolor import colored
print(colored('Success!', 'green'))
背景颜色输出
除了文字颜色,我们也可以将终端的背景改变成不同的颜色。
使用 termcolor
库中的 colored
方法的时候,如果要修改背景颜色,只需要在第二个参数中指定背景颜色即可。例如,下面的代码将输出红底白字的“Error!”字样:
from termcolor import colored
print(colored('Error!', 'white', 'on_red'))
除了红底白字以外,也有很多种背景颜色可以选择,例如:
- 黑色底(‘on_grey’)
- 红色底(‘on_red’)
- 绿色底(‘on_green’)
- 黄色底(‘on_yellow’)
- 蓝色底(‘on_blue’)
- 紫色底(‘on_magenta’)
- 青色底(‘on_cyan’)
- 白色底(‘on_white’)
二、相关问题
1、Python 使用pyinstaller打包后,print打印颜色乱码
问题描述:
Python 使用pyinstaller打包后,print打印颜色乱码,如图:
代码如下,直接运行是正常的,使用pyinstaller打包后运行乱码
class bcolors:
OKRED = '\033[1;31m'
END = '\033[0m'
print(bcolors.OKRED+'红色字体'+bcolors.OKRED)
解决办法:
添加如下代码即可。
import colorama
colorama.init(autoreset=True)
2、pyinstaller 打包pyqt5 图标不显示问题
问题描述:
pyqt5打包成exe,程序有图标,但是双击打开的窗口左上角没有显示小图标。
解决办法:
1.创建icon.qrc文件,在文件中写入下方代码,保存
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="/">
<file>icon.ico</file>
</qresource>
</RCC>
2.生成py文件,这个py文件把图片保存成二进制
pyrcc5 -o images.py images.qrc
3.导入模块
import images
MainWindow.setWindowIcon(QIcon(':/icon.ico'))
一般情况下,图标问题可以解决.如果还是不行,将窗口的小图标格式修改问 .png格式 icon.png 再执行以上步骤。
参考文章: