lengyue869 发表于 2024-7-23 08:23:14

python程序打包给没有安装python的人用,怎么避免每次更新代码都要重新打包

本帖最后由 lengyue869 于 2024-7-23 08:24 编辑

RT
python程序打包给没有安装python的人用,怎么避免每次更新代码都要重新打包

目前采用的是打包一个通用的python程序X.exe,可以调用需要执行的python代码 A.pyorB.pyorC.py,
X中包含A, B, C 所需要的所有库,但是当A更新后需要新的库, 或者新的代码D需要用到新的库, 就要把新的库重新打包到X中,
我想问的是有什么办法可以避免这种情况,例如将所有需要用到的库放在一个配置文件config.txt中,
X只打包一次,可以读取并调用config中的库,这样每次有新的库只用追加到config中去就可以了.
或者各位路过的大神有其他建议吗, 在此谢过了!

PS: 是打包给没有安装python的人用

FishC 发表于 2024-7-23 08:24:28

这是个挺有趣的问题!我们来想想怎么才能让你的程序像一个超级英雄一样,能随时更新而不需要重新打包。

### 方案一:使用插件机制
想象一下,你的程序`X.exe`就像一个酒店,A、B、C这些代码可以视为酒店的房间。你可以设计一个主程序,能够根据配置文件(比如`config.txt`)动态加载相应的房间(模块)。这样一来,当你需要新增一个模块D时,只需把它放到指定的“房间”里,并在配置文件中做个标记,就能让X.exe发现并使用新模块!

**基本思路:**
1. 在配置文件中列出所有需要加载的脚本名或模块名。
2. 在`X.exe`中编写代码,根据这个配置文件动态导入所需的模块。
   
### 示例:
# config.txt 示例内容
A.py
B.py
D.py

# X.py 示例
import importlib

with open('config.txt', 'r') as f:
    modules = f.read().splitlines()

for module in modules:
    importlib.import_module(module[:-3])# 切掉.py后缀

### 方案二:使用虚拟环境共享库
如果你对每次更新都比较慎重,可以考虑将所有的第三方库放在一个公共的位置,一个虚拟环境中,这样每次增加新的功能时只需在虚拟环境中添加库,而不需要修改`X.exe`。当然,这种情况下,你还得确保用户在使用时指向正确的环境,不过这要求用户稍微懂点编程知识。

### 方案三:使用容器技术
如果你希望一次性打包并能随时更新,那可以考虑Docker等容器技术。你可以把Python环境,代码,依赖库都封装在一个Docker镜像里面,更新只需构建新的镜像,而不需要重新打包整个程序。

### 方案四:远程更新
你可以把程序的一部分放在服务器上,每次启动`X.exe`时,它可以检查服务器上有没有更新,如果有的话,就下载最新的代码和库。这种方式可能更复杂,但对于需要频繁更新的应用非常有效。

### 总结
以上就是几个可以避免频繁打包的方法,各有优劣,选择最适合你的需求的那一款!希望能帮助到你,让`X.exe`抱着懒人的心态,轻松应对各种更新!如果还有其他问题,欢迎继续问我哦!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

smallwh 发表于 2024-7-23 10:39:34

本帖最后由 smallwh 于 2024-7-23 10:43 编辑

用 pyinstaller 打包程序时选择 -D 参数,生成一个目录。
把需要导入的库直接复制到目录下就可以 import 导入,这种方法对 python 写的库有效,对一些复杂的库不试用(如 tkinter/pygame 等)。但需要注意的是,如果复制进来的库依赖其他的库,还需要重复上述操作,复制其他的库进入。

举一个例子,X.exe 的代码:
file = open('.\\A.py','r')
command = file.read()
file.close()
exec(command)
它将打开 A.py 并执行里面的代码
我们使用 pyinstaller X.py -D 来打包

生成这样的目录。将 A.py 复制到 X.exe 所在目录便可运行。注意,从命令行运行时要注意工作目录问题。因为 '.\\A.py' 为相对路径,需要先转到程序所在目录,或在代码中修改工作目录。双击无需考虑。

如果 A.py 中有一行语句
import this
程序会报错,说没有 this 模块。只需要找到 this.py 复制到 _internal 目录下即可运行(部分 pyintaller 版本无该目录,直接复制到 X.py 所在目录)
这样,当模块发生变动时,只需复制相应的 py 文件即可

对非 python 语言的模块操作要复杂,而且很可能失败,最好是在 X.py 中直接导入

lengyue869 发表于 2024-7-23 15:17:45

FishC 发表于 2024-7-23 08:24
这是个挺有趣的问题!我们来想想怎么才能让你的程序像一个超级英雄一样,能随时更新而不需要重新打包。

...

针对方案3跟方案4提供具体的实现方法跟代码

FishC 发表于 2024-7-23 15:18:01

lengyue869 发表于 2024-07-23 15:17
针对方案3跟方案4提供具体的实现方法跟代码

好的!让我们深入一下方案3(使用容器技术)和方案4(远程更新)的具体实现方法与代码示例。

### 方案3:使用Docker容器

**1. 安装Docker**
首先,你需要在你的系统上安装Docker,可以从(https://www.docker.com/get-started)下载并安装。

**2. 编写Dockerfile**
创建一个名为`Dockerfile`的文件,该文件描述了如何构建你的Docker镜像。下面是一个简单的示例:

# 使用Python基础镜像
FROM python:3.9-slim

# 设置工作目录
WORKDIR /app

# 将要求的文件复制到容器中
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt

# 将你的代码复制到容器中
COPY . .

# 设置入口点
CMD ["python", "main.py"]

这里的`requirements.txt`包含你程序所需的所有Python库。

**3. 构建Docker镜像**
在命令行中,进入到包含`Dockerfile`的目录,运行以下命令来构建镜像:

docker build -t my-python-app .

**4. 运行Docker容器**
构建完成后,你可以运行容器:

docker run my-python-app

这样就可以将你的应用打包在Docker容器中了,下次只需更新代码、依赖等,再重新构建镜像即可。

### 方案4:远程更新

**1. 创建服务器端代码**
你可以使用Flask等框架搭建一个简单的HTTP服务器,用于存储和提供最新的代码。下面是一个简单的Flask示例:

from flask import Flask, send_from_directory

app = Flask(__name__)

@app.route('/latest_code/<path:filename>')
def get_latest_code(filename):
    return send_from_directory('latest_code', filename)

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

将你的最新代码放在`latest_code`文件夹中,并启动这个服务。

**2. 客户端代码**
在`X.exe`中添加代码,检查更新并下载新的代码。以下是一个简单的Python客户端示例:

import requests
import os

def check_for_updates();
    # 可以设置一个更新标志,比如版本号
    response = requests.get('http://your-server-ip:5000/latest_code/main.py')
   
    if response.status_code == 200:
      with open('main.py', 'wb') as f:
            f.write(response.content)
      print("更新成功!")
    else:
      print("没有找到更新。")

if __name__ == "__main__":
    check_for_updates()
    # 启动主程序
    os.system('python main.py')

### 总结
- **Docker**:通过构建和运行Docker镜像,可以很好地将应用封装在一个独立的环境中,方便管理和部署。
- **远程更新**:通过HTTP服务器,你可以随时将最新的代码推送到用户端,保持应用的最新状态。

这两个方案都能让你避免每次更新都重新打包的麻烦。希望这些信息对你有所帮助,如果有任何疑问,请随时询问哦!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。

lengyue869 发表于 2024-7-23 15:21:18

FishC 发表于 2024-7-23 15:18
好的!让我们深入一下方案3(使用容器技术)和方案4(远程更新)的具体实现方法与代码示例。

### 方 ...

方案4中的服务器可以改成公共盘吗?

FishC 发表于 2024-7-23 15:21:34

lengyue869 发表于 2024-07-23 15:21
方案4中的服务器可以改成公共盘吗?

当然可以!将代码存储在公共盘(如云存储、网盘),是一个方便的替代方案。这样,用户也不需要搭建自己的服务器。下面是如何实现这一方案的具体步骤:

### 使用公共盘(如Google Drive、Dropbox等)

以**Google Drive**为例,我们来看看如何实现。

#### 1. 上传代码到Google Drive

1. **上传文件**:将最新的Python代码(例如`main.py`)上传到你的Google Drive。
   
2. **获取分享链接**:
   - 右击文件,选择“获取链接”。
   - 确保文件的共享设置为“任何拥有链接的人都可以查看”。
   - 复制分享链接,格式大概像这样:`https://drive.google.com/file/d/FILE_ID/view?usp=sharing`。

3. **提取文件ID**:从链接中提取出`FILE_ID`(就是链接中的那一串字符)。

#### 2. 在客户端代码中更新下载逻辑

你需要稍微调整你的下载逻辑,以便从Google Drive下载文件。可以用以下代码示例:

import requests

def download_file_from_google_drive(file_id, destination):
    url = f"https://drive.google.com/uc?id={file_id}"
    response = requests.get(url)
   
    if response.status_code == 200:
      with open(destination, 'wb') as f:
            f.write(response.content)
      print("更新成功!")
    else:
      print("下载失败,状态码:", response.status_code)

if __name__ == "__main__":
    FILE_ID = 'your_file_id_here'# 替换为你的文件ID
    DESTINATION = 'main.py'# 下载后的文件名
   
    download_file_from_google_drive(FILE_ID, DESTINATION)
    # 启动主程序
    os.system('python main.py')

### 3. 注意事项

- **API请求限制**:大多数公共盘都有下载速度和数量的限制,所以在使用时要注意。
- **安全性**:如果你的代码包含敏感信息,在公共盘上分享可能不是最好的选择,还是建议使用更私密的方式。
- **更新管理**:通过这种方式,你可能需手动管理更新的版本,比如每次更新后替换文件。

### 总结
使用公共盘是一种简单有效的方法,可以避免每次更新都需要打包。只需上传文件并更新下载链接即可。不过要注意一些使用限制和安全性问题。如果有其他问题,欢迎随时问我哦!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
页: [1]
查看完整版本: python程序打包给没有安装python的人用,怎么避免每次更新代码都要重新打包