开发者

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

开发者 https://www.devze.com 2024-11-05 09:18 出处:网络 作者: 仙草哥哥
目录打包exe基础单文件pyinstaller安装准备文件使用pyinstaller打包隐藏控制台窗口添加图标多文件程序读取资源文件(相对路径)读取资源文件(打包入exe)import文件导入引用与致谢打包exe
目录
  • 打包exe
  • 基础单文件
    • pyinstaller安装
    • 准备文件
    • 使用pyinstaller打包
    • 隐藏控制台窗口
    • 添加图标
  • 多文件程序
    • 读取资源文件(相对路径)
    • 读取资源文件(打包入exe)
    • import文件导入
  • 引用与致谢

    打包exe

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

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

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

    基础单文件

    pyinstaller安装

    使用pip安编程客栈装pyinstaller:pip install pyinstaller

    准备文件

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

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

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

    使用pyinstaller打包

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

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

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

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

    隐藏控制台窗口

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

    pyinstaller --onefile --noconsole main.py
    

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

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

    import tkinter as tk
    from tkinter import scrolledtext
    import requests
     
     
    def fetch_data():
        try:
    EZuLEG        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()

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

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

    添加图标

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

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

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

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

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

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

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

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

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

    多文件程序

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

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

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

    下面是我们的程序:

    import json
     
    with 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 os
     
    def resopythonurce_path(relative_path):
        if hasattr(sys, "_MEIPASS"):
            base_path = sys._MEIPASS
        else:
            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 key
     
    print(key)
    

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

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

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

    引用与致谢

    pyinstaller

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

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

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

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

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

    以上就是python使用pyinstaller将代码打包为exe程序的详细内容,更多关于python pyinstaller代码打包为exe的资料请关注编程客栈(www.devze.com)其它相关文章!

    0

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    关注公众号