一鍵整合,萬用萬靈,Python3.10專案嵌入式一鍵整合包的製作(Embed)

劉悅的技術部落格發表於2023-11-16

我們知道Python是一門解釋型語言,專案執行時需要依賴Python直譯器,並且有時候需要安裝專案中對應的三方依賴庫。對於專業的Python開發者來說,可以直接透過pip命令進行安裝即可。但是如果是分發給其他的Windows使用者,特別是不熟悉Python的人來說,這樣過於繁瑣。因此最好的辦法是連同Python直譯器和Python專案打包在一起,透過嵌入式一鍵整合包解決專案的分發問題。

本次我們以一鍵扒譜的專案為例子,演示如何將專案直接打包為一鍵整合包,方便其他使用者執行使用。

嵌入式Python處理

首先克隆我們自己的專案:

git clone https://github.com/v3ucn/YiJianBaPu.git

正常流程是透過pip安裝專案的依賴。

但現在我們不直接透過pip安裝依賴,而是透過嵌入式的安裝包。

進入Python官方的下載頁面:

https://www.python.org/downloads/windows/

下載Windows embeddable package (64-bit)安裝包,注意是embeddable版本的,並不是傳統安裝包,同時版本也需要和開發專案的Python版本吻合:

隨後將其解壓到專案的根目錄,並且下載get-pip.py檔案,放入到剛剛解壓的安裝包內,下載地址:

https://bootstrap.pypa.io/get-pip.py

放入之後的目錄結構如下:

D:\work\YiJianBaPu\python310>tree /f  
Folder PATH listing for volume 新加捲  
Volume serial number is 9824-5798  
D:.  
    get-pip.py  
    libcrypto-1_1.dll  
    libffi-7.dll  
    libssl-1_1.dll  
    LICENSE.txt  
    pyexpat.pyd  
    python.cat  
    python.exe  
    python3.dll  
    python310.dll  
    python310.zip  
    python310._pth  
    pythonw.exe  
    select.pyd  
    sqlite3.dll  
    unicodedata.pyd  
    vcruntime140.dll  
    vcruntime140_1.dll  
    winsound.pyd  
    _asyncio.pyd  
    _bz2.pyd  
    _ctypes.pyd  
    _decimal.pyd  
    _elementtree.pyd  
    _hashlib.pyd  
    _lzma.pyd  
    _msi.pyd  
    _multiprocessing.pyd  
    _overlapped.pyd  
    _queue.pyd  
    _socket.pyd  
    _sqlite3.pyd  
    _ssl.pyd  
    _uuid.pyd  
    _zoneinfo.pyd

隨後在專案的根目錄執行命令:



.\python310\python.exe .\python310\get-pip.py


注意這裡的python.exe並不是本地開發環境的Python,而是嵌入式直譯器的Python。

此時我們的目錄中多出兩個資料夾Lib和Scripts:

D:\work\YiJianBaPu\python310>tree  
Folder PATH listing for volume 新加捲  
Volume serial number is 9824-5798  
D:.  
├───Lib  
│   └───site-packages  
│       ├───pip  
│       │   ├───_internal  
│       │   │   ├───cli  
│       │   │   │   └───__pycache__  
│       │   │   ├───commands  
│       │   │   │   └───__pycache__  
│       │   │   ├───distributions  
│       │   │   │   └───__pycache__  
│       │   │   ├───index  
│       │   │   │   └───__pycache__  
│       │   │   ├───locations  
│       │   │   │   └───__pycache__  
│       │   │   ├───metadata  
│       │   │   │   ├───importlib  
│       │   │   │   │   └───__pycache__  
│       │   │   │   └───__pycache__  
│       │   │   ├───models  
│       │   │   │   └───__pycache__  
│       │   │   ├───network  
│       │   │   │   └───__pycache__  
│       │   │   ├───operations  
│       │   │   │   ├───build  
│       │   │   │   │   └───__pycache__  
│       │   │   │   ├───install  
│       │   │   │   │   └───__pycache__  
│       │   │   │   └───__pycache__  
│       │   │   ├───req  
│       │   │   │   └───__pycache__  
│       │   │   ├───resolution  
│       │   │   │   ├───legacy  
│       │   │   │   │   └───__pycache__  
│       │   │   │   ├───resolvelib  
│       │   │   │   │   └───__pycache__  
│       │   │   │   └───__pycache__  
│       │   │   ├───utils  
│       │   │   │   └───__pycache__  
│       │   │   ├───vcs  
│       │   │   │   └───__pycache__  
│       │   │   └───__pycache__  
│       │   ├───_vendor  
│       │   │   ├───cachecontrol  
│       │   │   │   ├───caches  
│       │   │   │   │   └───__pycache__  
│       │   │   │   └───__pycache__  
│       │   │   ├───certifi  
│       │   │   │   └───__pycache__  
│       │   │   ├───chardet  
│       │   │   │   ├───cli  
│       │   │   │   │   └───__pycache__  
│       │   │   │   ├───metadata  
│       │   │   │   │   └───__pycache__  
│       │   │   │   └───__pycache__  
│       │   │   ├───colorama  
│       │   │   │   ├───tests  
│       │   │   │   │   └───__pycache__  
│       │   │   │   └───__pycache__  
│       │   │   ├───distlib  
│       │   │   │   └───__pycache__  
│       │   │   ├───distro  
│       │   │   │   └───__pycache__  
│       │   │   ├───idna  
│       │   │   │   └───__pycache__  
│       │   │   ├───msgpack  
│       │   │   │   └───__pycache__  
│       │   │   ├───packaging  
│       │   │   │   └───__pycache__  
│       │   │   ├───pkg_resources  
│       │   │   │   └───__pycache__  
│       │   │   ├───platformdirs  
│       │   │   │   └───__pycache__  
│       │   │   ├───pygments  
│       │   │   │   ├───filters  
│       │   │   │   │   └───__pycache__  
│       │   │   │   ├───formatters  
│       │   │   │   │   └───__pycache__  
│       │   │   │   ├───lexers  
│       │   │   │   │   └───__pycache__  
│       │   │   │   ├───styles  
│       │   │   │   │   └───__pycache__  
│       │   │   │   └───__pycache__  
│       │   │   ├───pyparsing  
│       │   │   │   ├───diagram  
│       │   │   │   │   └───__pycache__  
│       │   │   │   └───__pycache__  
│       │   │   ├───pyproject_hooks  
│       │   │   │   ├───_in_process  
│       │   │   │   │   └───__pycache__  
│       │   │   │   └───__pycache__  
│       │   │   ├───requests  
│       │   │   │   └───__pycache__  
│       │   │   ├───resolvelib  
│       │   │   │   ├───compat  
│       │   │   │   │   └───__pycache__  
│       │   │   │   └───__pycache__  
│       │   │   ├───rich  
│       │   │   │   └───__pycache__  
│       │   │   ├───tenacity  
│       │   │   │   └───__pycache__  
│       │   │   ├───tomli  
│       │   │   │   └───__pycache__  
│       │   │   ├───truststore  
│       │   │   │   └───__pycache__  
│       │   │   ├───urllib3  
│       │   │   │   ├───contrib  
│       │   │   │   │   ├───_securetransport  
│       │   │   │   │   │   └───__pycache__  
│       │   │   │   │   └───__pycache__  
│       │   │   │   ├───packages  
│       │   │   │   │   ├───backports  
│       │   │   │   │   │   └───__pycache__  
│       │   │   │   │   └───__pycache__  
│       │   │   │   ├───util  
│       │   │   │   │   └───__pycache__  
│       │   │   │   └───__pycache__  
│       │   │   ├───webencodings  
│       │   │   │   └───__pycache__  
│       │   │   └───__pycache__  
│       │   └───__pycache__  
│       ├───pip-23.3.1.dist-info  
│       ├───pkg_resources  
│       │   ├───extern  
│       │   │   └───__pycache__  
│       │   ├───_vendor  
│       │   │   ├───importlib_resources  
│       │   │   │   └───__pycache__  
│       │   │   ├───jaraco  
│       │   │   │   ├───text  
│       │   │   │   │   └───__pycache__  
│       │   │   │   └───__pycache__  
│       │   │   ├───more_itertools  
│       │   │   │   └───__pycache__  
│       │   │   ├───packaging  
│       │   │   │   └───__pycache__  
│       │   │   ├───platformdirs  
│       │   │   │   └───__pycache__  
│       │   │   └───__pycache__  
│       │   └───__pycache__  
│       ├───setuptools  
│       │   ├───command  
│       │   │   └───__pycache__  
│       │   ├───config  
│       │   │   ├───_validate_pyproject  
│       │   │   │   └───__pycache__  
│       │   │   └───__pycache__  
│       │   ├───extern  
│       │   │   └───__pycache__  
│       │   ├───_distutils  
│       │   │   ├───command  
│       │   │   │   └───__pycache__  
│       │   │   └───__pycache__  
│       │   ├───_vendor  
│       │   │   ├───importlib_metadata  
│       │   │   │   └───__pycache__  
│       │   │   ├───importlib_resources  
│       │   │   │   └───__pycache__  
│       │   │   ├───jaraco  
│       │   │   │   ├───text  
│       │   │   │   │   └───__pycache__  
│       │   │   │   └───__pycache__  
│       │   │   ├───more_itertools  
│       │   │   │   └───__pycache__  
│       │   │   ├───packaging  
│       │   │   │   └───__pycache__  
│       │   │   ├───tomli  
│       │   │   │   └───__pycache__  
│       │   │   └───__pycache__  
│       │   └───__pycache__  
│       ├───setuptools-68.2.2.dist-info  
│       └───_distutils_hack  
│           └───__pycache__  
└───Scripts

隨後修改python310._pth檔案,將內容改成下面這樣:

python310.zip  
.  
  
# Uncomment to run site.main() automatically  
import site

至此,嵌入式直譯器就配置好了。

嵌入式安裝依賴

此後,當我們需要安裝依賴時,必須用嵌入式的直譯器進行安裝:

.\python310\python.exe -m pip install noisereduce -t E:\work\YiJianBaPu\python310\Lib\site-packages

上面的命令展示如何嵌入式安裝依賴庫noisereduce。

這裡需要注意的時,直譯器必須是嵌入式直譯器.\python310\python.exe,同時透過-t引數來指定三方庫的位置,也就是說,必須安裝到專案的目錄中,而不是系統的預設開發環境目錄。

安裝成功後,我們必須可以在專案的目錄下可以找到這個庫:

D:\work\YiJianBaPu\python310\Lib\site-packages>tree  
Folder PATH listing for volume 新加捲  
Volume serial number is 9824-5798  
D:.  
├───noisereduce  
│   ├───spectralgate  
│   │   └───__pycache__  
│   ├───torchgate  
│   │   └───__pycache__  
│   └───__pycache__

如此,依賴和直譯器就緊密結合在一起了,換臺機器,並不需要安裝也可以直接啟動。

一鍵啟動

現在,我們來編寫一鍵啟動指令碼,launch.bat檔案:

@echo off  
chcp 65001  
@echo 開始執行  
call .\python310\python.exe -m spleeter separate -p spleeter:2stems -o ./output ./test.mp3  
call .\python310\python.exe ./infer.py --model ./ckpt/model_ckpt_steps_104000_simplified.ckpt --wav ./output/test/vocals.wav  
@echo 處理完畢,請按任意鍵  
call pause

這裡chcp命令用來宣告編碼,防止中文提示亂碼。

call用來執行指令碼,注意直譯器必須使用專案內建的嵌入式直譯器.\python310\python.exe

隨後雙擊執行指令碼launch.bat,程式返回:

Active code page: 65001  
開始執行  
INFO:spleeter:File ./output\test/vocals.wav written succesfully  
INFO:spleeter:File ./output\test/accompaniment.wav written succesfully  
accumulate_grad_batches: 1, audio_sample_rate: 44100, binarization_args: {'num_workers': 0, 'shuffle': True}, binarizer_cls: preprocessing.MIDIExtractionBinarizer, binary_data_dir: data/some_ds_fixmel_spk3_aug8/binary,  
clip_grad_norm: 1, dataloader_prefetch_factor: 2, ddp_backend: nccl, ds_workers: 4, finetune_ckpt_path: None,  
finetune_enabled: False, finetune_ignored_params: [], finetune_strict_shapes: True, fmax: 8000, fmin: 40,  
freezing_enabled: False, frozen_params: [], hop_size: 512, log_interval: 100, lr_scheduler_args: {'min_lr': 1e-05, 'scheduler_cls': 'lr_scheduler.scheduler.WarmupLR', 'warmup_steps': 5000},  
max_batch_frames: 80000, max_batch_size: 8, max_updates: 10000000, max_val_batch_frames: 10000, max_val_batch_size: 1,  
midi_extractor_args: {'attention_drop': 0.1, 'attention_heads': 8, 'attention_heads_dim': 64, 'conv_drop': 0.1, 'dim': 512, 'ffn_latent_drop': 0.1, 'ffn_out_drop': 0.1, 'kernel_size': 31, 'lay': 8, 'use_lay_skip': True}, midi_max: 127, midi_min: 0, midi_num_bins: 128, midi_prob_deviation: 1.0,  
midi_shift_proportion: 0.0, midi_shift_range: [-6, 6], model_cls: modules.model.Gmidi_conform.midi_conforms, num_ckpt_keep: 5, num_sanity_val_steps: 1,  
num_valid_plots: 300, optimizer_args: {'beta1': 0.9, 'beta2': 0.98, 'lr': 0.0001, 'optimizer_cls': 'torch.optim.AdamW', 'weight_decay': 0}, pe: rmvpe, pe_ckpt: pretrained/rmvpe/model.pt, permanent_ckpt_interval: 40000,  
permanent_ckpt_start: 200000, pl_trainer_accelerator: auto, pl_trainer_devices: auto, pl_trainer_num_nodes: 1, pl_trainer_precision: 32-true,  
pl_trainer_strategy: auto, raw_data_dir: [], rest_threshold: 0.1, sampler_frame_count_grid: 6, seed: 114514,  
sort_by_len: True, task_cls: training.MIDIExtractionTask, test_prefixes: None, train_set_name: train, units_dim: 80,  
units_encoder: mel, units_encoder_ckpt: pretrained/contentvec/checkpoint_best_legacy_500.pt, use_buond_loss: True, use_midi_loss: True, val_check_interval: 4000,  
valid_set_name: valid, win_size: 2048  
| load 'model' from 'ckpt\model_ckpt_steps_104000_simplified.ckpt'.  
100%|████████████████████████████████████████████████████████████████████████████████████| 2/2 [00:01<00:00,  1.88it/s]  
處理完畢,請按任意鍵  
Press any key to continue . . .

可以看到,執行結果和傳統終端執行的結果是一致的。

區別是使用者並不需要本地配置Python環境,只需要下載專案的整合包即可。

結語

透過嵌入式打包,可以把Python程式和直譯器、依賴庫一併打包分發給非專業使用者,由此就提高了這部分使用者群體的使用體驗,最後奉上打包後的整合包,以饗眾鄉親:

連結:https://pan.baidu.com/s/1HN3LAusdtofwqtb4gnSwvQ?pwd=72yq

相關文章