使用pyinstaller将python代码打包为exe程序

打包exe

对于不懂程序的人来说,可能有这样一个认识上的误区:只有能够直接打开的exe才是平常经常见到的程序,py文件不能算是程序。

在这种情况下,一些python的使用者可能非常苦恼:怎么才能够让我的程序,看起来像是真正的程序呢?

实际上,通过pyinstaller,我们就可以轻松将python代码打包为常见的exe程序,再也不会被他人看不起了(误)。

基础单文件

pyinstaller安装

使用pip安装pyinstaller:pip install pyinstaller

准备文件

我们需要准备一个需要打包的单文件,例如hello_world.py

print("hello world!!")# 为了防止我们的程序太快直接结束看不出效果
# 我们添加一个input()阻塞程序
input()

如果按照平常的使用,应该使用:python hello_world.py运行程序

使用pyinstaller打包

使用指令:pyinstaller --onefile hello_world.py

此时,会看到当前目录下已经生成了很多文件

 在dist目录下,就包含了我们已经生成好的hello_world.exe,通过双击运行,就可以看到程序运行的结果。

隐藏控制台窗口

如果你不需要一个控制台窗口,可以添加--noconsole选项。

pyinstaller --onefile --noconsole main.py

注意:如果你不需要控制台窗口,那么就不应该使用像input这样的需要控制台的函数。

通常,对于gui程序,隐藏控制台窗口是很有必要的。下面是一个简单的查看本地ip的例子(需要安装requests库)。

import tkinter as tk
from tkinter import scrolledtext
import requestsdef fetch_data():try:response = requests.get("http://httpbin.org/get")response.raise_for_status()data = response.json()info = f'您的当前的ip地址是:{data.get("origin")}'text_area.delete("1.0", tk.END)text_area.insert(tk.END, info) except requests.RequestException as e:text_area.delete("1.0", tk.END)text_area.insert(tk.END, f"请求失败: {e}")window = tk.Tk()
window.title("查看本地ip")text_area = scrolledtext.ScrolledText(window, width=60, height=20)
text_area.pack(padx=10, pady=10)fetch_button = tk.Button(window, text="获取数据", command=fetch_data)
fetch_button.pack(pady=5)window.mainloop()

对于这样一个程序,实际上是完全用不到控制台窗口的,所以隐藏窗口是更好的。

添加图标

默认的图标是很丑的(如图所示),如果我们需要我们的软件有一个更好看的图标,需要自己提供一个图标文件。

通过添加--icon=your_icon.ico选项,来为你的程序设置图标。

pyinstaller --onefile --icon=my_icon.ico main.py

图标不应该直接用一个图片作为图标,我们先需要通过程序制作一个图标,这里需要使用pillow库:

from PIL import Imageimg = Image.open("我的图片.png")# 为适应显示需求,可能需要考虑生成多个不同尺寸的icon
img = img.resize((256, 256))img.save("my_icon.ico", format="ICO")

现在,我们使用刚刚制作的图标,进行打包即可,下图为某个经典病毒的标志,但其实是我们自己制作图标并打包的,因此只是一个图片而已,并不是真的病毒程序。

注意:你可能遇到系统图标缓存未及时更新的问题,也就是说,你已经设置好了图标,但是由于系统没能及时更新并显示,你看到的仍然还是默认图标,因此怀疑自己是不是操作错了。其实这是没什么影响的,但如果你是一个急性子,一定要现在就看到效果,在windows系统中可以尝试输入命令ie4uinit.exe -show

 多文件程序

读取资源文件(相对路径)

假设,我们的程序需要通过json读取某个文件,这是一个json文件:

["跟仙草学py", "笑话大全", "绿野仙踪", "怎么样同莎碧交流"]

下面是我们的程序:

import jsonwith open("book.json", "r", encoding="utf-8") as f:books = json.load(f)for i in books:print(i)

那么,打包以后,是否还能正常使用呢?首先,我们应该明确一件事情,虽然我们自己知道我们需要一个json文件,但是目前对于pyinstaller来说,其并不知道这一点,因此,打包后,仍然只有单一的程序。

此时,我们可以选择将book.json(也就是我们需要用的存档文件),手动移动到程序路径下,这样就可以按照原本的相对路径读写。

读取资源文件(打包入exe)

对于资源文件,我们可以在打包指令上提出我们需要这些文件,使用--add-data选项添加,格式为:

对于windows系统,使用资源文件;目标路径

对于linux系统,使用资源文件:目标路径

pyinstaller --onefile --add-data "book.json;." main.py

如果需要添加多个文件,可以多次使用--add-data,如果要添加整个目录,也可以使用通配符*

如果我们这样做,情况将有所不同,此时文件并不存放在普通文件目录中,而是在临时的目录中,因此必须要修改原本的程序代码。

import json
import sys
import os# 获取资源文件的路径
if hasattr(sys, "_MEIPASS"):resource_path = os.path.join(sys._MEIPASS, "book.json")
else:resource_path = "book.json"with open(resource_path, "r", encoding="utf-8") as f:books = json.load(f)for i in books:print(i)

通常情况下,为了简化代码,在多处使用路径,应该封装这样一个函数:

import sys
import osdef resource_path(relative_path):if hasattr(sys, "_MEIPASS"):base_path = sys._MEIPASSelse:base_path = os.path.abspath(".")return os.path.join(base_path, relative_path)# 在代码中这样引入
resource_path = resource_path("book.json")

注意:sys._MEIPASS指向的目录是只读属性的,并不适合写入或者修改,因此,只应该用于资源的读取。如果有写入需求,应该将数据写入到用户系统的持久目录中(或者使用相对路径,并提示用户应该总是将文件整个目录一起移动)。

import文件导入

假如,我们需要通过import导入配置文件,例如,settings.py:

key = "sagegrass"

然后在程序中通过import导入

from settings import keyprint(key)

如果是这样的情况,那么无需担心导入文件会无法处理,通常交给pyinstaller自动解决即可。

我们只需要像普通打包一样,使用:pyinstaller --onefile main.py,而无需关心settings.py是否被包含。

注意:虽然pyinstaller可以处理直接导入,但是,无法处理动态导入,如果遇到这种情况,可以使用--hidden-import=module_name,进行手动导入。

引用与致谢

pyinstaller

使用pyinstaller打包确实有一些优点,包括:

  • 简化部署:目标机器上无需有python环境,可以直接通过打包好的程序运行。
  • 支持隐藏代码逻辑:python是一种明文的代码,因此任何人都能够查看源代码,而打包后可以一定程度上隐藏源代码,使得明文代码不直接可见(注意:专业的黑客或安全人员是有能力将其逆向还原的,因此,这并不是非常可靠的保证源代码不可见的方法)。

 当然,同样也有一些缺点:

  • 生成文件体积较大:由于python解释器,依赖库等都会被打包,即使是非常简单的一句代码,打包后都会变大很多。
  • 加载速度慢:打包为exe的性能远不如原生的py代码,尤其是对于onefile模式,运行时需要先解压,这个过程也会消耗很多时间

因此,要根据你的情况考虑是否使用pyinstaller,通常特别适合用于给不懂代码,没有python环境的人提供可执行程序的时候使用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/458758.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

博客搭建之路:hexo搜索引擎收录

文章目录 hexo搜索引擎收录以百度为例 hexo搜索引擎收录 hexo版本5.0.2 npm版本6.14.7 next版本7.8.0 写博客的目的肯定不是就只有自己能看到,想让更多的人看到就需要可以让搜索引擎来收录对应的文章。hexo支持生成站点地图sitemap 在hexo下的_config.yml中配置站点…

2-ZYNQ 折腾记录 -PMU

The AMD Zyng UltraScale MPSoC包括一个专用的用户可编程处理器,该平台测量单元(Platform Measurement Unit, PMU)处理器用于电源、错误管理和执行可选的软件测试库(Software Test Library, STL)用于功能安全应用。 PMU执行以下一组任务。启动前对系统的初始化。电…

Video-XL:面向小时级视频理解的超长视觉语言模型

在人工智能领域,视频理解一直是一个挑战性的任务,尤其是对于长时间视频内容的理解。现在,Video-XL的问世标志着我们在这一领域迈出了重要的一步。Video-XL是一个专为小时级视频理解设计的超长视觉语言模型,它能够处理超长视频序列…

BUUCTF之web篇

第一题 [极客大挑战 2019]EasySQL 打开靶机后可以看到这是一个登陆的页面 我们可以尝试两种方式登录 弱口令爆破(burpsuite) 通过SQL注入里的万能密码来跳过账户和密码验证的过程 这里就需要万能密码aor true # 在这里单引号的作用是结束用户名或者密码…

【Javaee】网络原理—http协议(一)

前言 本篇文章将详细介绍http协议,将介绍http抓包工具的下载与使用。 目录 一.http协议初识 1.概念 2.特点 1)版本 2)工作方式 二.http抓包工具 1.抓包是什么 2.抓包软件下载(Fiddler) 3.使用 三.http格式 …

04C++循环结构

//while 循环#include <iostream> using namespace std; int main() { int num0; while (num<10){ cout<<num<<endl; num; } return 0; } //do while语句 #include <iostream> using namespace std; int mai…

Appium中的api(一)

目录 1.基础python代码准备 1--参数的一些说明 2--python内所要编写的代码 解释 2.如何获取包名和界面名 1-api 2-完整代码 代码解释 3.如何关闭驱动连接 4.安装卸载app 1--卸载 2--安装 5.判断app是否安装 6.将应用放到后台在切换为前台的时间 7.UIAutomatorViewer的使用 1--找…

并联 高电压、高电流 放大器实现 2 倍输出电流模块±2A

1.1 并联输出电路设计注意事项 直接对两个功率运算放大器的输出进行硬接线并不是一种好的电气做法。如果两个运算放大器的输出直接连接在一起&#xff0c;则可能会导致不均匀的电流共享。这是因为其中的每个运算放大器都尝试强制施加略微不同的 Vout 电压&#xff0c;该电压取决…

vulnhub(16):sickos(两种打点方式)

端口 ip&#xff1a;192.168.72.154 nmap -Pn -p- 192.168.72.154 --min-rate 10000PORT STATE SERVICE 22 open ssh 3128 open http-proxy 8080 closed http-proxy web渗透方式一&#xff1a;web后台 正常访问80端口&#xff0c;是不开放的&#xff0c;我们需要配置…

高速定向广播声光预警系统赋能高速安全管控

近年来&#xff0c;高速重大交通事故屡见不鲜&#xff0c;安全管控一直是高速运营的重中之重。如何利用现代化技术和信息化手段&#xff0c;创新、智能、高效的压降交通事故的发生概率&#xff0c;优化交通安全管控质量&#xff0c;是近年来交管部门的主要工作&#xff0c;也是…

云原生Istio基础

一&#xff0e;Service Mesh 架构 Service Mesh&#xff08;服务网格&#xff09;是一种用于处理服务到服务通信的专用基础设施层。它的主要目的是将微服务之间复杂的通信和治理逻辑从微服务代码中分离出来&#xff0c;放到一个独立的层中进行管理。传统的微服务架构中&#x…

浅析Android View绘制过程中的Surface

前言 在《浅析Android中View的测量布局流程》中我们对VSYNC信号到达App进程之后开启的View布局过程进行了分析&#xff0c;经过对整个App界面的View树进行遍历完成了测量和布局&#xff0c;确定了View的大小以及在屏幕中所处的位置。但是&#xff0c;如果想让用户在屏幕上看到…

【十六进制数转十进制数 】

【十六进制数转十进制数 】 C语言版本C 版本Java版本Python版本 &#x1f490;The Begin&#x1f490;点点关注&#xff0c;收藏不迷路&#x1f490; 从键盘接收一个十六进制数&#xff0c;编程实现将其转换成十进制数。 输入 输入一个十六进制数 输出 输出一个十进制数 样…

GitHub 上的优质 Linux 开源项目,真滴硬核!

作为一名互联网人&#xff0c;提起 Linux 大家都不陌生&#xff0c;尤其是日常跟 Linux 操作系统打交道最多的&#xff0c;最熟悉不过了。互联网上关于 Linux 相关的教程和资料也非常的多&#xff0c;但是当你从中筛选出真正对自己有帮助的资料是需要花费很大精力与时间的。 G…

JVM基础(内存结构)

文章目录 内存结构JAVA堆方法区 &#xff08;Method Area&#xff09;运行时常量池&#xff08;Runtime Constant Pool&#xff09; 虚拟机栈 &#xff08;Java Virtual Machine Stack&#xff09;本地方法摘栈&#xff08;Native Method Stacks&#xff09;程序计数器&#xf…

交易的人生就是对未来不断的挑战!

在这个充满不确定性的市场中&#xff0c;我们每个人都渴望找到一条通往成功的路径。在Eagle Trader交易员中&#xff0c;有一位资深交易者&#xff0c;他不仅对交易有着不同寻常的执着和热爱&#xff0c;而且他的真诚见解和独到的交易哲学&#xff0c;可能会触动你的心弦。他的…

尚硅谷-react教程-求和案例-@redux-devtools/extension 开发者工具使用-笔记

## 7.求和案例_react-redux开发者工具的使用(1).npm install redux-devtools/extension(2).store中进行配置import { composeWithDevTools } from redux-devtools/extension;export default createStore(allReducer,composeWithDevTools(applyMiddleware(thunk))) src/redux/s…

OpenCV系列教程六:信用卡数字识别、人脸检测、车牌/答题卡识别、OCR

文章目录 一、信用卡数字识别1.1 模板匹配1.2 匹配多个对象1.3 处理数字模板1.4 预处理卡片信息&#xff0c;得到4组数字块。1.5 遍历数字块&#xff0c;将卡片中每个数字与模板数字进行匹配 二、人脸检测2.1人脸检测算法原理2.2 OpenCV中的人脸检测流程 三、车牌识别3.1 安装t…

一行代码,实现请假审批流程(Java版)

首先画一个流程图 测试流程图 activiti 项目基础配置 activiti 工作流引擎数据库设计 工作流引擎API 介绍 什么是BPMN流程图 工作流引擎同类对比 继续学习方向 总结 工作流审批功能是办公OA系统核心能力&#xff0c;如果让你设计一个工作流审批系统&#xff0c;你会吗…

SDK5(note中)

在原有SDK5(note上)里的代码上添加了 timer的消息 LRESULT OnCreate(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {OutputDebugString(_T("[11syy]WM_CREATE\n"));//创建一个计时器SetTimer(hwnd, 1, 1000, nullptr);return TRUE; }LRESULT OnClese(HWND …