Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[TWB] pdm 模式 #73

Closed
SOVLOOKUP opened this issue Jul 5, 2022 · 5 comments
Closed

[TWB] pdm 模式 #73

SOVLOOKUP opened this issue Jul 5, 2022 · 5 comments
Assignees
Labels

Comments

@SOVLOOKUP
Copy link
Contributor

Issue类型

建议 or 代码贡献请求

我的想法

pdm 是一个 python 包管理器,使项目拥有独立的依赖环境,并有非常清晰的依赖描述,例如:

[project]
name = "uie-api"
version = "0.0.1"
description = "paddlenlp uie web api"
authors = [
    {name = "sovlookup", email = "gonorth@qq.com"},
]
dependencies = [
    "paddlenlp>=2.3.3",
    "paddlepaddle>=2.3.0",
    "setuptools>=62.6.0",
    "fastapi>=0.78.0",
    "uvicorn[standard]>=0.18.2",
]
requires-python = ">=3.8"
license = {text = "MIT"}

一个 pdm 项目示例: https://github.com/SOVLOOKUP/uie-api

期待的回应

希望 qpt 能自动识别 pdm 项目,读取依赖及 python 环境等配置进行打包

@github-actions
Copy link

github-actions bot commented Jul 5, 2022

Hi,开发者朋友,鉴于您是首次在QPT下新增Issue,请务必参考给定的Issue模板进行Issue的新增。
虽然形如版本号、打包日志等信息可能对你并不重要,但如未提供则可能会严重拖慢Issue的解决效率,因为他们对于QPT的维护者而言非常重要!
如您未按Issue模板进行内容补充,可关闭此Issue或Edit该Issue,社区维护者会对低效Issue直接Close,请悉知!

@GT-ZhangAcer GT-ZhangAcer added the 已加入ToDo 不错的Feature label Jul 5, 2022
@GT-ZhangAcer
Copy link
Member

GT-ZhangAcer commented Jul 5, 2022

加入Todo ,等有空就学习一下哈哈哈

@SOVLOOKUP
Copy link
Contributor Author

如果能给我一些 tips (qpt 是如何进行依赖扫描的;如果我要改变扫描逻辑应该修改哪个文件),我可以帮助完成这个功能

@GT-ZhangAcer
Copy link
Member

GT-ZhangAcer commented Jul 6, 2022

这部分代码写的有点乱,各种写死打补丁哈哈哈(想重构也是可以的,最近实在有点忙)
主要分为两个大部分:

依赖检索

1.用户代码依赖检索

由于要判断哪些依赖需要被打包,所以要对用户代码进行检索,检索import的情况,根据import情况来判断用户可能用到了哪些依赖(绝大部分是可以这样检索得到)。
但这样也面临一个问题:import的是文件夹,而非真正的依赖名,例如opencv-python>=2.0在import时是import cv2,以及paddlepaddle在import时是import paddle,那么我们还需要对用户环境中的依赖情况检索才能判断import的文件夹名对应的是哪个依赖包,以及依赖包的版本。

该部分代码位于:https://github.com/QPT-Family/QPT/blob/%E5%BC%80%E5%8F%91%E5%88%86%E6%94%AF/qpt/kernel/qcode.py

2.用户环境依赖检索

由于使用pip、setuptools安装的依赖包,默认会在site_packages目录中给一个依赖包名_版本号_dist目录,这个目录下有Top_level.txt文件,文件中会记录该依赖对应的import名,通过对该文件的检索即可拿到import与依赖包名的关系。

同样,依赖包名_版本号_dist目录可以给我们很多信息,包括依赖的依赖情况(例如paddlepaddle依赖numpy、pillow),这部分可以通过pip来做检索(实际上我没玩透这个,而且pip更新很不向下兼容,以至于QPT要严格现在pip版本号)

该部分代码位于:

# Author: Acer Zhang

当前已知的Bug(Anaconda中部分包丢失Top_level.txt信息):#65

3.依赖匹配

在做完两部分检索后,就要进行依赖的匹配,生成一个requirement文件,包含主依赖+对应版本号+被注释掉的主依赖的依赖(pip会默认忽略,所以这里也默认注释了)

依赖封装

解析requirement

因为客户机不一定会安装VS2019这样的开发环境,所以例如lap这样原作者没有提供whl包的依赖,可能需要用户具备编译环境。未来更好让用户去控制依赖如何被封装,这里的requirement文件就多了一些特殊标识符(QPT目前还没弄太好) :

QPT_DISPLAY_FLAG = "#$QPT_FLAG$"
DISPLAY_IGNORE = "ignore"
DISPLAY_COPY = "copy" # 复制开发环境编译好的文件 - 文件列表也可以从`依赖包名_版本号_dist`目录里的RECORD或者installed-files.txt文件中找到
DISPLAY_FORCE = "force"  # 独立安装
DISPLAY_NET_INSTALL = "net_install"  # 打包时从第三方站点下载,部署时安装
DISPLAY_ONLINE_INSTALL = "online_install"  # 在线安装
DISPLAY_LOCAL_INSTALL = "local_install"  # 本地下载后安装
DISPLAY_SETUP_INSTALL = "setup_install"  # 直接安装

例如我们想避免在客户机上编译安装lap,那么requirement里就可以写为:
lap==xxx #$QPT_FLAG$copy

代码解析部分:

def analyze_requirements_file(file_path):

获取文件列表:

def get_package_all_file(package, site_package_path=None):

封装为SubModule

这部分是最烂的地方,太想重构了(

封装用于Requirement文件安装的SubModule例子:https://github.com/QPT-Family/QPT/blob/26723288a15efbc4627e7cfcff6443ec5460418b/qpt/modules/auto_requirements.py

实际上就是对CustomPackage这个类的批量实例化,CustomPackage实现代码如下:

class CustomPackage(SubModule):

Tips:
一个SubModule是由N个SubModuleOpt组成的,SubModuleOpt是最小执行单元,可以通过重写这个类的act方法来实现开发环境or用户环境要执行的操作(shell、pip等)
例如我们想封装一个下载whl文件的SubModuleOpt:https://github.com/QPT-Family/QPT/blob/%E5%BC%80%E5%8F%91%E5%88%86%E6%94%AF/qpt/modules/package.py#L44

然后封装在SubModule:https://github.com/QPT-Family/QPT/blob/%E5%BC%80%E5%8F%91%E5%88%86%E6%94%AF/qpt/modules/package.py#L201
-> self.add_pack_opt开发环境执行 self.add_unpack_opt客户环境执行

最后,加入到封装流程中:https://github.com/QPT-Family/QPT/blob/%E5%BC%80%E5%8F%91%E5%88%86%E6%94%AF/examples/advanced/%E4%BD%BF%E7%94%A8SubModule%E6%B7%BB%E5%8A%A0%E8%87%AA%E5%AE%9A%E4%B9%89whl.md

SubModule最开始设计时觉得能灵活解决很多问题了,但现在发现只有增加,并没有删除这个操作,可能后续还会再改进一下,基类源码部分在:https://github.com/QPT-Family/QPT/blob/%E5%BC%80%E5%8F%91%E5%88%86%E6%94%AF/qpt/modules/base.py

(请勿在SubModule中使用module_path等成员变量,因为这些变量只是占位,只有SubModuleOpt部分才会真实有效,这部分文档有空一定更新[狗头])

@GT-ZhangAcer
Copy link
Member

已经发布啦~感谢贡献

@GT-ZhangAcer GT-ZhangAcer pinned this issue Jul 24, 2022
@GT-ZhangAcer GT-ZhangAcer unpinned this issue Apr 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Status: Done
Development

No branches or pull requests

2 participants