From 8e73a33be10af5dc6f4b63deb28e55d2390c736d Mon Sep 17 00:00:00 2001 From: Kissablecho Date: Tue, 8 Jul 2025 13:20:17 +0800 Subject: [PATCH 01/27] Update dev_package_and_upload.yml (#17) --- .github/workflows/dev_package_and_upload.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev_package_and_upload.yml b/.github/workflows/dev_package_and_upload.yml index 0dbcc34..dc149f7 100644 --- a/.github/workflows/dev_package_and_upload.yml +++ b/.github/workflows/dev_package_and_upload.yml @@ -68,6 +68,6 @@ jobs: name: Artifact path: | ./dist/*.exe - retention-days: 90 + retention-days: 14 if-no-files-found: warn overwrite: true From e0f9d10699025763ea608df2e46bcfd73c0ac78f Mon Sep 17 00:00:00 2001 From: God-2077 Date: Tue, 8 Jul 2025 16:03:09 +0800 Subject: [PATCH 02/27] =?UTF-8?q?=E6=9B=B4=E6=96=B0=20NetEase=5FCloud=5FMu?= =?UTF-8?q?sic=5FDownload?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 +- package/nuitka_config.yml | 4 +- .../README.md" | 8 +- .../v.25-07-08.py" | 261 ++++++++++++++++++ 4 files changed, 273 insertions(+), 6 deletions(-) create mode 100644 "\347\275\221\346\230\223\344\272\221\351\237\263\344\271\220\346\255\214\345\215\225\346\211\271\351\207\217\344\270\213\350\275\275\346\255\214\346\233\262/v.25-07-08.py" diff --git a/README.md b/README.md index 00e25a9..9978790 100644 --- a/README.md +++ b/README.md @@ -8,12 +8,14 @@ ## [网易云音乐歌单批量下载歌曲][1] -最新版:[v.24-10-06][2] +使用 metting api 批量下载网易云音乐歌曲 + +注意,这程序严重依赖第三方的 metting api ## [键盘监听][4] -最新版:[v.24.07.16][5] +键盘监听 ## [psql_terminal][7] diff --git a/package/nuitka_config.yml b/package/nuitka_config.yml index 43fb293..b037efb 100644 --- a/package/nuitka_config.yml +++ b/package/nuitka_config.yml @@ -33,8 +33,8 @@ output-name-template: '{{name}}_{{version}}_nuitka_{{os}}_{{arch}}' - name: 'NetEase_Cloud_Music_Download' - version: 'v.24-10-06' - python-file: '网易云音乐歌单批量下载歌曲\v.24-10-06.py' + version: 'v.25-07-08' + python-file: '网易云音乐歌单批量下载歌曲\v.25-07-08.py' install-requirements: [ 'quote', 'requests', diff --git "a/\347\275\221\346\230\223\344\272\221\351\237\263\344\271\220\346\255\214\345\215\225\346\211\271\351\207\217\344\270\213\350\275\275\346\255\214\346\233\262/README.md" "b/\347\275\221\346\230\223\344\272\221\351\237\263\344\271\220\346\255\214\345\215\225\346\211\271\351\207\217\344\270\213\350\275\275\346\255\214\346\233\262/README.md" index e5f88ad..1046f88 100644 --- "a/\347\275\221\346\230\223\344\272\221\351\237\263\344\271\220\346\255\214\345\215\225\346\211\271\351\207\217\344\270\213\350\275\275\346\255\214\346\233\262/README.md" +++ "b/\347\275\221\346\230\223\344\272\221\351\237\263\344\271\220\346\255\214\345\215\225\346\211\271\351\207\217\344\270\213\350\275\275\346\255\214\346\233\262/README.md" @@ -4,7 +4,7 @@ 注意,这程序严重依赖第三方的 metting api -最新版:[v.24-10-06][7] +最新版:[v.25-07-08][8] ## 说明 @@ -24,6 +24,9 @@ python ***.py ## 日志 +- [v.25-07-08][8] + - 删去 `#!/usr/bin/python` 指令 + - [v.24-10-06][7] - 小优化 - 添加了是否下载小于60秒音乐的选项 @@ -60,4 +63,5 @@ python ***.py [4]: https://github.com/God-2077/python-code/blob/main/%E7%BD%91%E6%98%93%E4%BA%91%E9%9F%B3%E4%B9%90%E6%AD%8C%E5%8D%95%E6%89%B9%E9%87%8F%E4%B8%8B%E8%BD%BD%E6%AD%8C%E6%9B%B2/v.24-04-05.%E6%9C%80%E7%BB%88%E7%89%88.py [5]: https://github.com/God-2077/python-code/blob/main/%E7%BD%91%E6%98%93%E4%BA%91%E9%9F%B3%E4%B9%90%E6%AD%8C%E5%8D%95%E6%89%B9%E9%87%8F%E4%B8%8B%E8%BD%BD%E6%AD%8C%E6%9B%B2/v.24-07-18.py [6]: https://github.com/God-2077/python-code/blob/main/%E7%BD%91%E6%98%93%E4%BA%91%E9%9F%B3%E4%B9%90%E6%AD%8C%E5%8D%95%E6%89%B9%E9%87%8F%E4%B8%8B%E8%BD%BD%E6%AD%8C%E6%9B%B2/v.24-07-19.py -[7]: https://github.com/God-2077/python-code/blob/main/%E7%BD%91%E6%98%93%E4%BA%91%E9%9F%B3%E4%B9%90%E6%AD%8C%E5%8D%95%E6%89%B9%E9%87%8F%E4%B8%8B%E8%BD%BD%E6%AD%8C%E6%9B%B2/v.24-10-06.py \ No newline at end of file +[7]: https://github.com/God-2077/python-code/blob/main/%E7%BD%91%E6%98%93%E4%BA%91%E9%9F%B3%E4%B9%90%E6%AD%8C%E5%8D%95%E6%89%B9%E9%87%8F%E4%B8%8B%E8%BD%BD%E6%AD%8C%E6%9B%B2/v.24-10-06.py +[8]: v.24-10-06.py \ No newline at end of file diff --git "a/\347\275\221\346\230\223\344\272\221\351\237\263\344\271\220\346\255\214\345\215\225\346\211\271\351\207\217\344\270\213\350\275\275\346\255\214\346\233\262/v.25-07-08.py" "b/\347\275\221\346\230\223\344\272\221\351\237\263\344\271\220\346\255\214\345\215\225\346\211\271\351\207\217\344\270\213\350\275\275\346\255\214\346\233\262/v.25-07-08.py" new file mode 100644 index 0000000..eded536 --- /dev/null +++ "b/\347\275\221\346\230\223\344\272\221\351\237\263\344\271\220\346\255\214\345\215\225\346\211\271\351\207\217\344\270\213\350\275\275\346\255\214\346\233\262/v.25-07-08.py" @@ -0,0 +1,261 @@ +# -*- coding: UTF-8 -*- + +import os +import requests +from mutagen.mp3 import MP3 +import time +import signal +import sys +import re +from tabulate import tabulate + + +def download_file(url, file_path, file_type, index, total_files, timeout=10): + try: + response = requests.get(url, stream=True, timeout=timeout) + response.raise_for_status() + total_size = int(response.headers.get('content-length', 0)) + downloaded_size = 0 + + with open(file_path, "wb") as file: + for data in response.iter_content(chunk_size=4096): + downloaded_size += len(data) + file.write(data) + progress = downloaded_size / total_size * 100 if total_size > 0 else 0 + print(f"正在下载 [{index}/{total_files}][{file_type}] {file_path},进度:{progress:.2f}%\r", end="") + + print(f"下载完成 [{index}/{total_files}][{file_type}] {file_path}") + return True + except requests.exceptions.RequestException as e: + print(f"下载 [{index}/{total_files}][{file_type}] {file_path} 失败:{e}") + return False + + +def download_lyrics(url, lrc_path, song_index, total_songs): + try: + response = requests.get(url, timeout=10) + response.raise_for_status() + with open(lrc_path, "w", encoding="utf-8") as lrc_file: + lrc_file.write(response.content.decode('utf-8')) + print(f"下载完成 [{song_index}/{total_songs}][LRC] {lrc_path}") + return True + except requests.exceptions.RequestException as e: + print(f"下载歌词失败:{e}") + return False + + +def safe_filename(filename): + invalid_chars = '\\/:*?"<>|' + for char in invalid_chars: + filename = filename.replace(char, '_') + return filename + + +def delete_file(file_path): + if os.path.exists(file_path): + os.remove(file_path) + print(f"删除文件:{file_path}") + + +def song_table(data): + table_data = [] + for idx, item in enumerate(data, start=1): + name = item['name'] + artist = item['artist'] + url_id = re.search(r'\d+', item['url']).group() + table_data.append([idx, name, artist, url_id]) + table_headers = ["序号", "标题", "艺术家", "ID"] + table = tabulate(table_data, table_headers, tablefmt="pipe") + print(table) + + +def exit_ctrl_c(sig, frame): + print("\n退出程序...") + sys.exit(0) + + +def welcome(): + print("welcome") + print("欢迎使用我开发的小程序") + print("Github Rope: https://github.com/God-2077/python-code/") + print("-------------------------") + print("网易云音乐歌单批量下载歌曲") + + +def download_playlist(playlist_id, download_path): + if not playlist_id.isdigit(): + print("歌单ID必须为数字") + return + + error_song_name = [] + error_song_id = [] + + api_urls = [ + "https://meting.qjqq.cn/?type=playlist&id=", + "https://api.injahow.cn/meting/?type=playlist&id=", + "https://meting-api.mnchen.cn/?type=playlist&id=", + "https://meting-api.mlj-dragon.cn/meting/?type=playlist&id=" + ] + + selected_api = None + data = None + + for api_url in api_urls: + try: + response = requests.get(f"{api_url}{playlist_id}", timeout=10) + # if requests.status_codes != 200: + # print("出错了...") + # print(f"状态码:{requests.status_codes}") + # return + response.raise_for_status() + data = response.json() + selected_api = api_url + if 'error' in data: + error = data.get("error", "") + print("出错了...") + print(f"错误详细:{error}") + return + break + except requests.exceptions.RequestException as e: + print(f"API {api_url} 请求失败:{e}") + continue + + if not data: + print("所有API都无法获取数据") + return + + os.makedirs(download_path, exist_ok=True) + + print(f"Meting API: {selected_api}") + + total_songs = len(data) + print(f"歌单共有 {total_songs} 首歌曲") + song_table(data) + envisage_size = total_songs * 7.7 + print(f"歌单共有 {total_songs} 首歌曲,预计歌曲文件总大小为 {envisage_size} MB") + chose = str(input("是否继续下载?(yes): ")) + if chose not in ["y", "", "yes"]: + print("退出程序...") + sys.exit(0) + chose = str(input("是否下载小于 60 秒的歌曲(可能为试听音乐)?(not): ")) + if chose not in ["y", "", "yes"]: + downtrymusic = 1 + else: + downtrymusic = 0 + successful_downloads = 0 + failed_downloads = [] + + def signal_handler(sig, frame): + print("\n检测到Ctrl+C, exiting gracefully...") + print(f"程序运行完成,共 {total_songs} 首歌曲,成功下载 {successful_downloads} 首歌曲") + if failed_downloads: + print(f"共有 {len(failed_downloads)} 首歌曲下载失败") + print("失败列表如下") + table_data = [[i + 1, error_song_name[i], error_song_id[i]] for i in range(len(error_song_name))] + print(tabulate(table_data, headers=["序号", "标题 - 艺术家", "ID"], tablefmt="grid")) + sys.exit(0) + + signal.signal(signal.SIGINT, signal_handler) + + for index, song in enumerate(data, start=1): + name = song.get("name", "") + artist = song.get("artist", "") + url = song.get("url", "") + lrc = song.get("lrc", "") + pic = song.get("pic", "") + + if not name or not artist or not url or not lrc: + print(f"歌曲信息不完整:{song}") + continue + + song_filename = f"{safe_filename(name)} - {safe_filename(artist)}.mp3" + song_name = f"{safe_filename(name)} - {safe_filename(artist)}" + song_path = os.path.join(download_path, song_filename) + + retry_count = 0 + while retry_count < 5: + if download_file(url, song_path, "MP3", index, total_songs): + successful_downloads += 1 + state = True + break + else: + retry_count += 1 + print(f"重试下载 [{index}/{total_songs}][MP3] {song_path},次数:{retry_count}") + state = False + time.sleep(1) + if state == False: + print("") + match = re.search(r'\d+', url) + error_song_id.append(int(match.group())) + error_song_name.append(song_name) + failed_downloads.append(match) + + if state == True: + try: + audio = MP3(song_path) + audio_duration = audio.info.length + if downtrymusic == 1: + if audio_duration < 60: + print(f"歌曲时长小于一分钟,删除歌曲和取消下载歌词和图片:{song_path}") + delete_file(song_path) + audio_duration_TF = False + successful_downloads -= 1 + match = re.search(r'\d+', url) + error_song_id.append(int(match.group())) + error_song_name.append(song_name) + else: + print(f"歌曲时长为 {audio_duration} 秒") + audio_duration_TF = True + else: + print(f"歌曲时长为 {audio_duration} 秒") + audio_duration_TF = True + except Exception as e: + print(f"无法获取歌曲时长:{e}") + print("应该为 VIP 单曲,删除歌曲文件和取消下载歌词和图片") + delete_file(song_path) + audio_duration_TF = False + successful_downloads -= 1 + match = re.search(r'\d+', url) + error_song_id.append(int(match.group())) + error_song_name.append(song_name) + failed_downloads.append(match) + + if audio_duration_TF: + lrc_filename = f"{safe_filename(name)} - {safe_filename(artist)}.lrc" + lrc_path = os.path.join(download_path, lrc_filename) + + retry_count = 0 + while retry_count < 5: + if download_lyrics(lrc, lrc_path, index, total_songs): + break + else: + retry_count += 1 + print(f"重试下载 [{index}/{total_songs}][LRC] {lrc_path},次数:{retry_count}") + time.sleep(1) + + pic_filename = f"{safe_filename(name)} - {safe_filename(artist)}.jpg" + pic_path = os.path.join(download_path, pic_filename) + + retry_count = 0 + while retry_count < 5: + if download_file(pic, pic_path, "PIC", index, total_songs): + break + else: + retry_count += 1 + print(f"重试下载 [{index}/{total_songs}][PIC] {pic_path},次数:{retry_count}") + time.sleep(1) + + print(f"程序运行完成,共 {total_songs} 首歌曲,成功下载 {successful_downloads} 首歌曲") + if failed_downloads or error_song_name: + print(f"共有 {len(failed_downloads)} 首歌曲下载失败") + print("失败列表如下") + table_data = [[i + 1, error_song_name[i], error_song_id[i]] for i in range(len(error_song_name))] + print(tabulate(table_data, headers=["序号", "标题 - 艺术家", "ID"], tablefmt="grid")) + + +if __name__ == "__main__": + signal.signal(signal.SIGINT, exit_ctrl_c) + welcome() + playlist_id = input("歌单ID:") + download_path = input(r"下载路径(默认为 ./down):") or r"./down" + download_playlist(playlist_id, download_path) From 4e7652aab0868248a438551045b58c86ae588bf2 Mon Sep 17 00:00:00 2001 From: Kissablecho Date: Tue, 8 Jul 2025 16:11:24 +0800 Subject: [PATCH 03/27] sync (#19) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Update dev_package_and_upload.yml * Update README.md * update nuitka_build.py * Update pyinstaller_package_and_release.yml * Update nuitka_package_release.yml * Update nuitka_build.py * 更新 NetEase_Cloud_Music_Download (#18) * Update dev_package_and_upload.yml (#17) * 更新 NetEase_Cloud_Music_Download --- .github/workflows/nuitka_package_release.yml | 1 + .../workflows/pyinstaller_package_and_release.yml | 3 ++- .gitignore | 3 ++- README.md | 3 ++- package/nuitka_build.py | 12 +++++++++--- package/nuitka_config.yml | 10 +++++----- 6 files changed, 21 insertions(+), 11 deletions(-) diff --git a/.github/workflows/nuitka_package_release.yml b/.github/workflows/nuitka_package_release.yml index a76f7a1..490faf2 100644 --- a/.github/workflows/nuitka_package_release.yml +++ b/.github/workflows/nuitka_package_release.yml @@ -84,5 +84,6 @@ jobs: generate_release_notes: true draft: false prerelease: false + overwrite_files: true files: | dist/*.exe diff --git a/.github/workflows/pyinstaller_package_and_release.yml b/.github/workflows/pyinstaller_package_and_release.yml index 8b9dec5..1cfc4fa 100644 --- a/.github/workflows/pyinstaller_package_and_release.yml +++ b/.github/workflows/pyinstaller_package_and_release.yml @@ -72,6 +72,7 @@ jobs: generate_release_notes: true draft: false prerelease: false + overwrite_files: true files: | dist/*.exe @@ -83,4 +84,4 @@ jobs: # file: "./dist/*.exe" # release_id: ${{ steps.create_release.outputs.id }} # verbose: false - # overwrite: true \ No newline at end of file + # overwrite: true diff --git a/.gitignore b/.gitignore index 352a4ed..8651081 100644 --- a/.gitignore +++ b/.gitignore @@ -198,4 +198,5 @@ cython_debug/ .temp temp/ .vscode/ -.idea/ \ No newline at end of file +.idea/ +**/*.bak \ No newline at end of file diff --git a/README.md b/README.md index 9978790..1ee898d 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,8 @@ **禁止任何人将代码用于违法行为** -[![Auto Package and Release](https://github.com/God-2077/python-code/actions/workflows/auto_package_and_release.yml/badge.svg)](https://github.com/God-2077/python-code/actions/workflows/auto_package_and_release.yml)[![Dev Package and Upload(dev)](https://github.com/God-2077/python-code/actions/workflows/dev_package_and_upload.yml/badge.svg?branch=dev)](https://github.com/God-2077/python-code/actions/workflows/dev_package_and_upload.yml) +[![Nuitka Package and Release](https://github.com/God-2077/python-code/actions/workflows/nuitka_package_release.yml/badge.svg)](https://github.com/God-2077/python-code/actions/workflows/nuitka_package_release.yml) +[![Nuitka Package and Upload(dev)](https://github.com/God-2077/python-code/actions/workflows/dev_package_and_upload.yml/badge.svg)](https://github.com/God-2077/python-code/actions/workflows/dev_package_and_upload.yml) ## [网易云音乐歌单批量下载歌曲][1] diff --git a/package/nuitka_build.py b/package/nuitka_build.py index d2ae578..63e6644 100644 --- a/package/nuitka_build.py +++ b/package/nuitka_build.py @@ -6,6 +6,8 @@ import argparse from pathlib import Path # from zip import zip_files_and_folders +import uuid +import shutil def main(): print("="*50) @@ -92,7 +94,7 @@ def main(): '--mingw64', # '--mode', '--assume-yes-for-downloads', #自动下载外部代码 - '--show-memory' + # '--show-memory' ] @@ -120,8 +122,12 @@ def main(): # print(f"警告: UPX目录不存在 {upx_dir}") # else: # print("不使用UPX压缩") + # 添加主Python文件 - cmd.append(str(python_file)) + t_file = str(uuid.uuid4()) + ".py" + t_file_path = base_dir / t_file + shutil.copy(str(python_file), t_file_path) + cmd.append(str(t_file_path)) # 打印并执行命令 print("执行命令:", ' '.join(cmd)) @@ -137,7 +143,7 @@ def main(): result = subprocess.run(cmd) if result.returncode == 0: - print(f"(onefile)打包成功: {dist_path / output_name}") + print(f"打包成功: {dist_path / output_name}") success_count += 1 else: print(f"打包失败,退出码: {result.returncode}") diff --git a/package/nuitka_config.yml b/package/nuitka_config.yml index b037efb..ab84c07 100644 --- a/package/nuitka_config.yml +++ b/package/nuitka_config.yml @@ -13,7 +13,7 @@ icon: windows-disable-console: False distpath: 'dist' - timeout: 1200 + timeout: 2700 output-name-template: '{{name}}_{{version}}_nuitka_{{os}}_{{arch}}' - name: 'Keyboard_monitoring' @@ -29,7 +29,7 @@ icon: windows-disable-console: False distpath: 'dist' - timeout: 1200 + timeout: 2700 output-name-template: '{{name}}_{{version}}_nuitka_{{os}}_{{arch}}' - name: 'NetEase_Cloud_Music_Download' @@ -46,7 +46,7 @@ icon: windows-disable-console: False distpath: 'dist' - timeout: 1200 + timeout: 2700 output-name-template: '{{name}}_{{version}}_nuitka_{{os}}_{{arch}}' - name: 'ftp_server' @@ -60,7 +60,7 @@ icon: windows-disable-console: False distpath: 'dist' - timeout: 1200 + timeout: 2700 output-name-template: '{{name}}_{{version}}_nuitka_{{os}}_{{arch}}' - name: 'sunrise_sunset_info' @@ -74,5 +74,5 @@ icon: windows-disable-console: False distpath: 'dist' - timeout: 1200 + timeout: 2700 output-name-template: '{{name}}_{{version}}_nuitka_{{os}}_{{arch}}' From cbc2deba62cca7eb6505bb199d6f46d69cbb0212 Mon Sep 17 00:00:00 2001 From: Kissablecho Date: Tue, 8 Jul 2025 18:26:53 +0800 Subject: [PATCH 04/27] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E4=BE=9D=E8=B5=96?= =?UTF-8?q?=E9=A1=B9=EF=BC=8C=E6=B7=BB=E5=8A=A0psutil=E5=92=8Castropy?= =?UTF-8?q?=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package/nuitka_config.yml | 6 ++++-- sunrise_sunset_info/README.md | 2 +- .../requirements.txt" | 3 ++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/package/nuitka_config.yml b/package/nuitka_config.yml index ab84c07..dbecf52 100644 --- a/package/nuitka_config.yml +++ b/package/nuitka_config.yml @@ -22,7 +22,8 @@ install-requirements: [ 'keyboard', 'configparser', - 'pywin32' + 'pywin32', + 'psutil' ] # upx: true # onefile: 1 @@ -67,7 +68,8 @@ version: 'v.25.05.02' python-file: 'sunrise_sunset_info\sunrise_sunset_info_v.25.05.02.py' install-requirements: [ - 'pyftpdlib' + 'pyftpdlib', + 'astropy' ] # upx: true # onefile: 1 # 0:文件夹 1:单文件 2:两者 diff --git a/sunrise_sunset_info/README.md b/sunrise_sunset_info/README.md index 68e527c..25a80a7 100644 --- a/sunrise_sunset_info/README.md +++ b/sunrise_sunset_info/README.md @@ -11,7 +11,7 @@ 安装第三方库 ```bash -pip install pyftpdlib +pip install pyftpdlib astropy ``` 运行 diff --git "a/\351\224\256\347\233\230\347\233\221\345\220\254/requirements.txt" "b/\351\224\256\347\233\230\347\233\221\345\220\254/requirements.txt" index 797f784..d208169 100644 --- "a/\351\224\256\347\233\230\347\233\221\345\220\254/requirements.txt" +++ "b/\351\224\256\347\233\230\347\233\221\345\220\254/requirements.txt" @@ -1,3 +1,4 @@ keyboard configparser -pywin32 \ No newline at end of file +pywin32 +psutil \ No newline at end of file From 77a6a2bdc505357c8cea2cdb9979b8a3e7a1964a Mon Sep 17 00:00:00 2001 From: Kissablecho Date: Tue, 8 Jul 2025 19:13:40 +0800 Subject: [PATCH 05/27] =?UTF-8?q?=E6=B7=BB=E5=8A=A0favicon.ico=E5=9B=BE?= =?UTF-8?q?=E6=A0=87=E6=96=87=E4=BB=B6=EF=BC=8C=E5=B9=B6=E5=9C=A8=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E4=B8=AD=E5=90=AF=E7=94=A8UPX=E5=8E=8B=E7=BC=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package/assets/favicon.ico | Bin 0 -> 18739 bytes package/nuitka_build.py | 26 +++++++++++++------------- package/nuitka_config.yml | 20 ++++++++++---------- 3 files changed, 23 insertions(+), 23 deletions(-) create mode 100644 package/assets/favicon.ico diff --git a/package/assets/favicon.ico b/package/assets/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..194939622bce828655d99e0eae2618c14954cc5d GIT binary patch literal 18739 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 literal 0 HcmV?d00001 diff --git a/package/nuitka_build.py b/package/nuitka_build.py index 63e6644..a24bb23 100644 --- a/package/nuitka_build.py +++ b/package/nuitka_build.py @@ -106,22 +106,22 @@ def main(): if icon: icon_path = base_dir / icon if icon_path.exists(): - cmd.extend(['--windows-icon-from-ico=icon.ico', str(icon_path)]) + cmd.append(f'--windows-icon-from-ico={str(icon_path)}') else: print(f"警告: 图标文件不存在 {icon_path}") - # if arrch == "ARM64": - # print("UPX不支持当前架构") - # else: - # if use_upx: - # if upx_dir.exists(): - # cmd.append('--plugin-enable=upx') - # cmd.extend(['--upx-binary', str(upx_dir)]) - # print(f"使用UPX压缩: {upx_dir}") - # else: - # print(f"警告: UPX目录不存在 {upx_dir}") - # else: - # print("不使用UPX压缩") + if arrch == "ARM64": + print("UPX不支持当前架构") + else: + if use_upx: + if upx_dir.exists(): + cmd.append('--plugin-enable=upx') + cmd.append(f'--upx-binary={str(upx_dir)}') + print(f"使用UPX压缩: {upx_dir}") + else: + print(f"警告: UPX目录不存在 {upx_dir}") + else: + print("不使用UPX压缩") # 添加主Python文件 t_file = str(uuid.uuid4()) + ".py" diff --git a/package/nuitka_config.yml b/package/nuitka_config.yml index dbecf52..d900093 100644 --- a/package/nuitka_config.yml +++ b/package/nuitka_config.yml @@ -8,9 +8,9 @@ 'rich', 'Pillow' ] - # upx: true + upx: true # onefile: 2 # 0:文件夹 1:单文件 2:两者 - icon: + icon: package\assets\favicon.ico windows-disable-console: False distpath: 'dist' timeout: 2700 @@ -25,9 +25,9 @@ 'pywin32', 'psutil' ] - # upx: true + upx: true # onefile: 1 - icon: + icon: package\assets\favicon.ico windows-disable-console: False distpath: 'dist' timeout: 2700 @@ -42,9 +42,9 @@ 'tabulate', 'mutagen' ] - # upx: true + upx: true # onefile: 1 - icon: + icon: package\assets\favicon.ico windows-disable-console: False distpath: 'dist' timeout: 2700 @@ -56,9 +56,9 @@ install-requirements: [ 'pyftpdlib' ] - # upx: true + upx: true # onefile: 1 - icon: + icon: package\assets\favicon.ico windows-disable-console: False distpath: 'dist' timeout: 2700 @@ -71,9 +71,9 @@ 'pyftpdlib', 'astropy' ] - # upx: true + upx: true # onefile: 1 # 0:文件夹 1:单文件 2:两者 - icon: + icon: package\assets\favicon.ico windows-disable-console: False distpath: 'dist' timeout: 2700 From 571e1ee3d4fc97a1c8e3dff15d0af4246438df59 Mon Sep 17 00:00:00 2001 From: God-2077 Date: Tue, 8 Jul 2025 21:23:34 +0800 Subject: [PATCH 06/27] =?UTF-8?q?Nuitka=20Build=20=E5=90=AF=E7=94=A8?= =?UTF-8?q?=E5=A4=9A=E6=A0=B8=E5=B9=B6=E8=A1=8C=E7=BC=96=E8=AF=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package/nuitka_build.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/package/nuitka_build.py b/package/nuitka_build.py index d19853f..86d4863 100644 --- a/package/nuitka_build.py +++ b/package/nuitka_build.py @@ -26,13 +26,14 @@ def main(): print(f"当前操作系统: {Machine} {arrch}") print(f"平台详情: {platform.platform()}") + print("CPU核心数:", os.cpu_count()) print(f"Python版本: {sys.version}") # 解析命令行参数 parser = argparse.ArgumentParser(description='Nuitka打包脚本') parser.add_argument('config', help='配置文件路径') args = parser.parse_args() - + cpu_count=os.cpu_count() # 读取配置文件 with open(args.config, 'r', encoding='utf-8') as f: config = yaml.safe_load(f) @@ -92,6 +93,7 @@ def main(): '--onefile', # 单文件 '--standalone', '--mingw64', + f'--jobs={os.cpu_count()}', # 多线程 # '--mode', '--assume-yes-for-downloads', #自动下载外部代码 # '--show-memory' From 8ab03e6f6bad95ef16dfe4fbf2d59fe7b1f150d5 Mon Sep 17 00:00:00 2001 From: God-2077 Date: Wed, 9 Jul 2025 01:33:55 +0800 Subject: [PATCH 07/27] test cache --- .github/workflows/dev_package_and_upload.yml | 56 ++++++++++++++++++-- 1 file changed, 51 insertions(+), 5 deletions(-) diff --git a/.github/workflows/dev_package_and_upload.yml b/.github/workflows/dev_package_and_upload.yml index dc149f7..364bfbb 100644 --- a/.github/workflows/dev_package_and_upload.yml +++ b/.github/workflows/dev_package_and_upload.yml @@ -1,16 +1,19 @@ -name: Nuitka Package and Upload(dev) +name: Nuitka Package and Release on: workflow_dispatch: push: branches: - - dev + - main paths: - 'package/nuitka_config.yml' jobs: - package-and-upload: + package-and-release: runs-on: windows-latest + env: + PYTHON_VERSION: 3.10 + NUITKA_CACHE_DIR: ${{ github.workspace }}/nuitka-cache # 添加必要的权限 permissions: @@ -23,17 +26,51 @@ jobs: - name: Checkout code uses: actions/checkout@v4 + + - name: Generate version tag + id: version + run: | + # 使用 UTC 时间确保一致性 + $date = (Get-Date).ToUniversalTime().ToString("yy.MM.dd") + $tag = "v$date" + $release = "Release $date" + echo "tag=$tag" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append + echo "release_name=$release" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append + - name: Set up Python uses: actions/setup-python@v5 with: - python-version: '3.10' - + python-version: ${{ env.PYTHON_VERSION }} + + - name: Cache UPX + id: cache-upx + uses: actions/cache@v4 + with: + path: upx + key: ${{ runner.os }}-${{ runner.arch }}-upx-v5.0.1 + restore-keys: | + ${{ runner.os }}-${{ runner.arch }}-upx- + - name: UPX Setup + if: ${{ steps.cache-upx.outputs.cache-hit != 'true' } run: | mkdir upx curl -o upx/upx.exe https://assets.ksable.top/github/upx/upx/v5.0.1/windows-amd64/upx.exe + - name: get pip cache dir + id: pip-cache-dir + run: echo "pip-cache-dir=$(pip cache dir)" >> $env:GITHUB_OUTPUT + + - name: pip cache + uses: actions/cache@v4 + with: + path: ${{ steps.pip-cache-dir.outputs.dir }} # pip缓存路径 + key: ${{ runner.os }}-${{ runner.arch }}-pip-${{ hashFiles('package/nuitka_build.py') }} + restore-keys: | + ${{ runner.os }}-${{ runner.arch }}-pip- # 后备恢复键(当精确键不存在时,使用最近的缓存) + + - name: Install dependencies run: | python -m pip install --upgrade pip @@ -53,6 +90,15 @@ jobs: # # 设置控制台编码为UTF-8 # chcp.com 65001 + - name: Cache Nuitka cache directory + uses: actions/cache@v4 + with: + path: ${{ env.NUITKA_CACHE_DIR }} + key: nuitka-${{ runner.os }}-${{ runner.arch }}-python-${{ env.PYTHON_VERSION }}-nuitka-${{ hashFiles('package/nuitka_build.py') }} + restore-keys: | + nuitka-${{ runner.os }}-${{ runner.arch }}-python-${{ env.PYTHON_VERSION }}- + nuitka-${{ runner.os }}-${{ runner.arch }}- + - name: Run packaging script run: | # 设置Python使用UTF-8编码 From 117f181b7b1e36ac74f5e21803c0f24ef4b0c82c Mon Sep 17 00:00:00 2001 From: God-2077 Date: Wed, 9 Jul 2025 01:35:40 +0800 Subject: [PATCH 08/27] =?UTF-8?q?=E5=88=A0=E5=8E=BB=E9=94=99=E8=AF=AF?= =?UTF-8?q?=E7=89=88=E6=9C=AC=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- novel_crawler/novel_crawler_v.25.07.08.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/novel_crawler/novel_crawler_v.25.07.08.py b/novel_crawler/novel_crawler_v.25.07.08.py index 91fe75b..b6269ee 100644 --- a/novel_crawler/novel_crawler_v.25.07.08.py +++ b/novel_crawler/novel_crawler_v.25.07.08.py @@ -417,7 +417,7 @@ def download_chapter(chapter_info, progress, task_id, chapter_count): # 主函数开始 def main(): - print_header("小说爬虫工具\n版本 v.25.07.07") + print_header("小说爬虫工具") if debug: logger.debug("Debug模式已开启") From ef83c93d1e18a9b4e6eeed04918209a90ec595b1 Mon Sep 17 00:00:00 2001 From: Kissablecho Date: Wed, 9 Jul 2025 01:49:19 +0800 Subject: [PATCH 09/27] fix dev_package_and_upload.yml --- .github/workflows/dev_package_and_upload.yml | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/.github/workflows/dev_package_and_upload.yml b/.github/workflows/dev_package_and_upload.yml index 364bfbb..12d93e5 100644 --- a/.github/workflows/dev_package_and_upload.yml +++ b/.github/workflows/dev_package_and_upload.yml @@ -1,10 +1,10 @@ -name: Nuitka Package and Release +name: Nuitka Package and Upload(dev) on: workflow_dispatch: push: branches: - - main + - dev paths: - 'package/nuitka_config.yml' @@ -27,15 +27,6 @@ jobs: - name: Checkout code uses: actions/checkout@v4 - - name: Generate version tag - id: version - run: | - # 使用 UTC 时间确保一致性 - $date = (Get-Date).ToUniversalTime().ToString("yy.MM.dd") - $tag = "v$date" - $release = "Release $date" - echo "tag=$tag" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append - echo "release_name=$release" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append - name: Set up Python From 63c3af4144e2e87ca23c9c6cae1b22910a996563 Mon Sep 17 00:00:00 2001 From: Kissablecho Date: Wed, 9 Jul 2025 01:58:28 +0800 Subject: [PATCH 10/27] fix dev_package_and_upload.yml --- .github/workflows/dev_package_and_upload.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev_package_and_upload.yml b/.github/workflows/dev_package_and_upload.yml index 12d93e5..73392e1 100644 --- a/.github/workflows/dev_package_and_upload.yml +++ b/.github/workflows/dev_package_and_upload.yml @@ -44,7 +44,7 @@ jobs: ${{ runner.os }}-${{ runner.arch }}-upx- - name: UPX Setup - if: ${{ steps.cache-upx.outputs.cache-hit != 'true' } + if: ${{ steps.cache-upx.outputs.cache-hit != 'true' }} run: | mkdir upx curl -o upx/upx.exe https://assets.ksable.top/github/upx/upx/v5.0.1/windows-amd64/upx.exe From 3b306ad3764414cb59f47b0d258a235f74a2d9c6 Mon Sep 17 00:00:00 2001 From: Kissablecho Date: Wed, 9 Jul 2025 02:05:22 +0800 Subject: [PATCH 11/27] fix dev_package_and_upload.yml pip-cache-dir --- .github/workflows/dev_package_and_upload.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev_package_and_upload.yml b/.github/workflows/dev_package_and_upload.yml index 73392e1..752f86e 100644 --- a/.github/workflows/dev_package_and_upload.yml +++ b/.github/workflows/dev_package_and_upload.yml @@ -56,7 +56,7 @@ jobs: - name: pip cache uses: actions/cache@v4 with: - path: ${{ steps.pip-cache-dir.outputs.dir }} # pip缓存路径 + path: ${{ steps.pip-cache-dir.outputs.pip-cache-dir }} # pip缓存路径 key: ${{ runner.os }}-${{ runner.arch }}-pip-${{ hashFiles('package/nuitka_build.py') }} restore-keys: | ${{ runner.os }}-${{ runner.arch }}-pip- # 后备恢复键(当精确键不存在时,使用最近的缓存) From 92f2afe16ce4243791f2e241beafb10b1b1cd767 Mon Sep 17 00:00:00 2001 From: Kissablecho Date: Wed, 9 Jul 2025 02:24:10 +0800 Subject: [PATCH 12/27] Update dev_package_and_upload.yml fix type --- .github/workflows/dev_package_and_upload.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev_package_and_upload.yml b/.github/workflows/dev_package_and_upload.yml index 752f86e..e37fe98 100644 --- a/.github/workflows/dev_package_and_upload.yml +++ b/.github/workflows/dev_package_and_upload.yml @@ -12,7 +12,7 @@ jobs: package-and-release: runs-on: windows-latest env: - PYTHON_VERSION: 3.10 + PYTHON_VERSION: '3.10' NUITKA_CACHE_DIR: ${{ github.workspace }}/nuitka-cache # 添加必要的权限 From 34541cebd3da5f29c978c8fdeaa4b9c0ce29a382 Mon Sep 17 00:00:00 2001 From: Kissablecho Date: Wed, 9 Jul 2025 11:27:48 +0800 Subject: [PATCH 13/27] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=AF=B9=E6=8F=92?= =?UTF-8?q?=E4=BB=B6=E7=9A=84=E6=94=AF=E6=8C=81=EF=BC=8C=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6=E4=BB=A5=E5=90=AF=E7=94=A8?= =?UTF-8?q?UPX=E6=8F=92=E4=BB=B6=E5=92=8C=E8=87=AA=E5=AE=9A=E4=B9=89?= =?UTF-8?q?=E5=91=BD=E4=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package/nuitka_build.py | 42 ++++++++++++++++++++++++++++++--------- package/nuitka_config.yml | 25 ++++++++++++++++++----- 2 files changed, 53 insertions(+), 14 deletions(-) diff --git a/package/nuitka_build.py b/package/nuitka_build.py index 86d4863..76c2692 100644 --- a/package/nuitka_build.py +++ b/package/nuitka_build.py @@ -56,6 +56,8 @@ def main(): dist_path = base_dir / task['distpath'] requirements = task.get('install-requirements', []) use_upx = task.get('upx', False) + enable_plugins = task.get('enable-plugins', []) + # onefile = task.get('onefile', 0) icon = task.get('icon') windows_disable_console = task.get('windows-disable-console', False) @@ -66,7 +68,7 @@ def main(): if arrch == "AMD64": arrch = "x64" output_name = output_name_template.replace('{{name}}', name).replace('{{version}}', version).replace('{{arch}}', arrch).replace('{{os}}', Machine) - + custom_command = task.get('custom-command') # 检查操作系统和架构 # if Machine not in task.get('os', []): # print(f"警告: 任务 [{i}/{len(config)} {task['name']}] 不支持当前操作系统 {Machine}") @@ -113,20 +115,42 @@ def main(): print(f"警告: 图标文件不存在 {icon_path}") - if arrch == "ARM64": - print("UPX不支持当前架构") - else: - if use_upx: + # if arrch == "ARM64": + # print("UPX不支持当前架构") + # else: + # if use_upx: + # if upx_dir.exists(): + # cmd.append('--plugin-enable=upx') + # cmd.append(f'--upx-binary={str(upx_dir)}') + # print(f"使用UPX压缩: {upx_dir}") + # else: + # print(f"警告: UPX目录不存在 {upx_dir}") + # else: + # print("不使用UPX压缩") + + if enable_plugins: + plugin_list = '' + if len(enable_plugins) == 1: + plugin_list = enable_plugins[0] + else: + plugin_list = ','.join(enable_plugins) + cmd.append(f'--plugin-enable={plugin_list}') + if 'upx' in enable_plugins: if upx_dir.exists(): - cmd.append('--plugin-enable=upx') cmd.append(f'--upx-binary={str(upx_dir)}') print(f"使用UPX压缩: {upx_dir}") else: print(f"警告: UPX目录不存在 {upx_dir}") - else: - print("不使用UPX压缩") - # 添加主Python文件 + if custom_command: + # custom_command 为 str + if isinstance(custom_command, str): + cmd.extend(custom_command.split()) + # custom_command 为 list + elif isinstance(custom_command, list): + cmd.extend(custom_command) + + # 避免中文等特殊字符导致编译报错 t_file = str(uuid.uuid4()) + ".py" t_file_path = base_dir / t_file shutil.copy(str(python_file), t_file_path) diff --git a/package/nuitka_config.yml b/package/nuitka_config.yml index d900093..c77d3fb 100644 --- a/package/nuitka_config.yml +++ b/package/nuitka_config.yml @@ -8,13 +8,16 @@ 'rich', 'Pillow' ] - upx: true + enable-plugins: [ + 'upx' + ] # onefile: 2 # 0:文件夹 1:单文件 2:两者 icon: package\assets\favicon.ico windows-disable-console: False distpath: 'dist' timeout: 2700 output-name-template: '{{name}}_{{version}}_nuitka_{{os}}_{{arch}}' + custom-command: [] - name: 'Keyboard_monitoring' version: 'v.24.07.16' @@ -25,13 +28,16 @@ 'pywin32', 'psutil' ] - upx: true + enable-plugins: [ + 'upx' + ] # onefile: 1 icon: package\assets\favicon.ico windows-disable-console: False distpath: 'dist' timeout: 2700 output-name-template: '{{name}}_{{version}}_nuitka_{{os}}_{{arch}}' + custom-command: [] - name: 'NetEase_Cloud_Music_Download' version: 'v.25-07-08' @@ -42,13 +48,16 @@ 'tabulate', 'mutagen' ] - upx: true + enable-plugins: [ + 'upx' + ] # onefile: 1 icon: package\assets\favicon.ico windows-disable-console: False distpath: 'dist' timeout: 2700 output-name-template: '{{name}}_{{version}}_nuitka_{{os}}_{{arch}}' + custom-command: [] - name: 'ftp_server' version: 'v.25-05-02' @@ -56,13 +65,16 @@ install-requirements: [ 'pyftpdlib' ] - upx: true + enable-plugins: [ + 'upx' + ] # onefile: 1 icon: package\assets\favicon.ico windows-disable-console: False distpath: 'dist' timeout: 2700 output-name-template: '{{name}}_{{version}}_nuitka_{{os}}_{{arch}}' + custom-command: [] - name: 'sunrise_sunset_info' version: 'v.25.05.02' @@ -71,10 +83,13 @@ 'pyftpdlib', 'astropy' ] - upx: true + enable-plugins: [ + 'upx' + ] # onefile: 1 # 0:文件夹 1:单文件 2:两者 icon: package\assets\favicon.ico windows-disable-console: False distpath: 'dist' timeout: 2700 output-name-template: '{{name}}_{{version}}_nuitka_{{os}}_{{arch}}' + custom-command: [] From c673c96bf6f3e4fa1548a3b5a0da333c10178790 Mon Sep 17 00:00:00 2001 From: Kissablecho Date: Wed, 9 Jul 2025 12:15:14 +0800 Subject: [PATCH 14/27] =?UTF-8?q?=E7=A6=81=E7=94=A8=20Nuitka=20Package=20a?= =?UTF-8?q?nd=20Upload(dev)=20=E8=87=AA=E5=8A=A8=E6=B5=81=E7=A8=8B?= =?UTF-8?q?=EF=BC=8C=E5=90=AF=E7=94=A8=E6=89=8B=E5=8A=A8=E8=A7=A6=E5=8F=91?= =?UTF-8?q?=EF=BC=8C=E6=B7=BB=E5=8A=A0=E6=B5=8B=E8=AF=95=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev_package_and_upload.yml | 34 +++++++++--- package/hello_world.py | 55 ++++++++++++++++++++ package/nuitka_test_config.yml | 16 ++++++ 3 files changed, 99 insertions(+), 6 deletions(-) create mode 100644 package/hello_world.py create mode 100644 package/nuitka_test_config.yml diff --git a/.github/workflows/dev_package_and_upload.yml b/.github/workflows/dev_package_and_upload.yml index e37fe98..c148d9d 100644 --- a/.github/workflows/dev_package_and_upload.yml +++ b/.github/workflows/dev_package_and_upload.yml @@ -2,11 +2,22 @@ name: Nuitka Package and Upload(dev) on: workflow_dispatch: - push: - branches: - - dev - paths: - - 'package/nuitka_config.yml' + inputs: + test: + description: '测试' + required: true + type: boolean + default: true + config_path: + description: '测试模式时用的配置文件路径(非测试时请忽略)' + required: true + type: string + default: 'package/nuitka_test_config.yml' + # push: + # branches: + # - dev + # paths: + # - 'package/nuitka_config.yml' jobs: package-and-release: @@ -91,6 +102,7 @@ jobs: nuitka-${{ runner.os }}-${{ runner.arch }}- - name: Run packaging script + if: ${{ !github.event.inputs.test }} run: | # 设置Python使用UTF-8编码 [System.Environment]::SetEnvironmentVariable('PYTHONUTF8', '1', 'Process') @@ -98,11 +110,21 @@ jobs: chcp.com 65001 cd package python nuitka_build.py nuitka_config.yml + + - name: Run Test packaging script + if: ${{ github.event.inputs.test }} + run: | + # 设置Python使用UTF-8编码 + [System.Environment]::SetEnvironmentVariable('PYTHONUTF8', '1', 'Process') + # 设置控制台编码为UTF-8 + chcp.com 65001 + cd package + python nuitka_build.py nuitka_test_config.yml - name: Upload files with wildcards uses: actions/upload-artifact@v4 with: - name: Artifact + name: ${{ runner.os }}-${{ runner.arch }}-${{ github.event.inputs.test && 'test-' || '' }}artifact path: | ./dist/*.exe retention-days: 14 diff --git a/package/hello_world.py b/package/hello_world.py new file mode 100644 index 0000000..ed9692d --- /dev/null +++ b/package/hello_world.py @@ -0,0 +1,55 @@ +import platform +import os +import sys +import psutil +print('='*50) + +# 显示系统信息 +print('hello world') +print('-'*50) +print('系统信息') +print("操作系统:", platform.system()) +print("架构:", platform.machine()) +print("版本:", platform.version()) +print("平台:", platform.platform()) + +# 显示硬件信息 +print('-'*50) +print('CPU 信息') +print(f"CPU 核心数: {psutil.cpu_count(logical=False)}") +print(f"逻辑处理器数: {psutil.cpu_count(logical=True)}") +print("处理器信息:", platform.processor()) +cpu_times = psutil.cpu_times() +print(f"用户时间: {cpu_times.user}") +print(f"系统时间: {cpu_times.system}") +print(f"空闲时间: {cpu_times.idle}") + +memory_info = psutil.virtual_memory() + +print('-'*50) +print('内存 信息') +print(f"总内存: {memory_info.total / (1024 ** 3)} GB") +print(f"空闲内存: {memory_info.free / (1024 ** 3)} GB") +print(f"已用内存: {memory_info.used / (1024 ** 3)} GB") +print(f"可用内存: {memory_info.available / (1024 ** 3)} GB") + +# 获取内存详细信息 +print('-'*50) +print('交换内存 信息') +swap_memory = psutil.swap_memory() +print(f"交换内存总量: {swap_memory.total / (1024 ** 3)} GB") +print(f"已用交换内存: {swap_memory.used / (1024 ** 3)} GB") +print(f"可用交换内存: {swap_memory.free / (1024 ** 3)} GB") + +print("系统编码:", sys.getdefaultencoding()) +print("文件系统编码:", sys.getfilesystemencoding()) + + + +# 显示Python信息 +print("Python版本:", sys.version) +print("Python路径:", sys.executable) +print("当前工作目录:", os.getcwd()) + + +print('='*50) diff --git a/package/nuitka_test_config.yml b/package/nuitka_test_config.yml new file mode 100644 index 0000000..9306565 --- /dev/null +++ b/package/nuitka_test_config.yml @@ -0,0 +1,16 @@ +- name: 'hello_world' + version: 'v.25.07.08' + python-file: 'package\hello_world.py' + install-requirements: [ + 'psutil' + ] + enable-plugins: [ + 'upx' + ] + # onefile: 2 # 0:文件夹 1:单文件 2:两者 + icon: package\assets\favicon.ico + windows-disable-console: False + distpath: 'dist' + timeout: 2700 + output-name-template: '{{name}}_{{version}}_nuitka_{{os}}_{{arch}}' + custom-command: [] From b20d849ef0b10ac909711967abb7c055ed2cec25 Mon Sep 17 00:00:00 2001 From: Kissablecho Date: Wed, 9 Jul 2025 13:02:18 +0800 Subject: [PATCH 15/27] fix Nuitka Package and Upload(dev) --- .github/workflows/dev_package_and_upload.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev_package_and_upload.yml b/.github/workflows/dev_package_and_upload.yml index c148d9d..b6d6d8b 100644 --- a/.github/workflows/dev_package_and_upload.yml +++ b/.github/workflows/dev_package_and_upload.yml @@ -119,7 +119,7 @@ jobs: # 设置控制台编码为UTF-8 chcp.com 65001 cd package - python nuitka_build.py nuitka_test_config.yml + python nuitka_build.py ${{ github.event.inputs.config_path }} - name: Upload files with wildcards uses: actions/upload-artifact@v4 From 6ecca80478bdbb2fdab190f4297b98c620548463 Mon Sep 17 00:00:00 2001 From: Kissablecho Date: Wed, 9 Jul 2025 13:32:55 +0800 Subject: [PATCH 16/27] try fix nuitka_build.py --- package/nuitka_build.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/package/nuitka_build.py b/package/nuitka_build.py index 76c2692..49f0cd1 100644 --- a/package/nuitka_build.py +++ b/package/nuitka_build.py @@ -33,14 +33,18 @@ def main(): parser = argparse.ArgumentParser(description='Nuitka打包脚本') parser.add_argument('config', help='配置文件路径') args = parser.parse_args() - cpu_count=os.cpu_count() - # 读取配置文件 - with open(args.config, 'r', encoding='utf-8') as f: - config = yaml.safe_load(f) # 基础路径设置 base_dir = Path(__file__).parent.parent # 项目根目录 upx_dir = base_dir / './upx/' # UPX目录 + + # 读取配置文件 + config_path = base_dir / args.config + if not config_path.exists(): + print(f"错误: 配置文件不存在 {config_path}") + sys.exit(1) + with open(str(config_path), 'r', encoding='utf-8') as f: + config = yaml.safe_load(f) success_count = 0 task_error_list = [] @@ -55,7 +59,6 @@ def main(): python_file = base_dir / task['python-file'] dist_path = base_dir / task['distpath'] requirements = task.get('install-requirements', []) - use_upx = task.get('upx', False) enable_plugins = task.get('enable-plugins', []) # onefile = task.get('onefile', 0) @@ -164,6 +167,7 @@ def main(): except subprocess.TimeoutExpired: print(f"任务[{i}/{len(config)} {task['name']}] 执行超时 {timeout} 秒") print(f"任务[{i}/{len(config)} {task['name']}]失败: {e}") + os.remove(t_file_path) task_error_list.append(task['name']) continue else: @@ -171,9 +175,11 @@ def main(): if result.returncode == 0: print(f"打包成功: {dist_path / output_name}") + os.remove(t_file_path) success_count += 1 else: print(f"打包失败,退出码: {result.returncode}") + os.remove(t_file_path) except Exception as e: print(f"任务[{i}/{len(config)} {task['name']}]失败: {e}") task_error_list.append(task['name']) From 98eb78ff16ab450abbfc5929979df53455a9a703 Mon Sep 17 00:00:00 2001 From: Kissablecho Date: Wed, 9 Jul 2025 14:12:35 +0800 Subject: [PATCH 17/27] Nuitka Package and Upload(dev) update upx installer and use more os bulid --- .github/workflows/dev_package_and_upload.yml | 59 +++++++++++++++++--- 1 file changed, 51 insertions(+), 8 deletions(-) diff --git a/.github/workflows/dev_package_and_upload.yml b/.github/workflows/dev_package_and_upload.yml index b6d6d8b..cbd55e2 100644 --- a/.github/workflows/dev_package_and_upload.yml +++ b/.github/workflows/dev_package_and_upload.yml @@ -20,11 +20,15 @@ on: # - 'package/nuitka_config.yml' jobs: - package-and-release: - runs-on: windows-latest + package-and-upload: + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, ubuntu-24.04-arm, windows-latest, windows-11-arm] env: PYTHON_VERSION: '3.10' NUITKA_CACHE_DIR: ${{ github.workspace }}/nuitka-cache + UPXVERSION: '5.0.1' # 添加必要的权限 permissions: @@ -44,21 +48,60 @@ jobs: uses: actions/setup-python@v5 with: python-version: ${{ env.PYTHON_VERSION }} - + - name: Cache UPX id: cache-upx uses: actions/cache@v4 with: path: upx - key: ${{ runner.os }}-${{ runner.arch }}-upx-v5.0.1 + key: ${{ runner.os }}-${{ runner.arch }}-upx-v${{ UPXVERSION }} restore-keys: | ${{ runner.os }}-${{ runner.arch }}-upx- - - - name: UPX Setup + + - name: Create UPX directory if: ${{ steps.cache-upx.outputs.cache-hit != 'true' }} + run: mkdir -p ./upx + + - name: Install UPX on Linux + if: ${{ runner.os == 'Linux' && steps.cache-upx.outputs.cache-hit != 'true' }} + run: | + case "${{ runner.arch }}" in + amd64) + UPX_ARCH=x86_64 + ;; + arm64) + UPX_ARCH=aarch64 + ;; + esac + + UPX_VERSION=${{ UPXVERSION}} + UPX_URL="https://github.com/upx/upx/releases/download/v${UPX_VERSION}/upx-${UPX_VERSION}-linux-${UPX_ARCH}.tar.xz" + + curl -L "$UPX_URL" -o upx.tar.xz + tar -xf upx.tar.xz -C ./upx --strip-components=1 + chmod +x ./upx/upx + + shell: bash + + - name: Install UPX on Windows + if: ${{ runner.os == 'Windows' && steps.cache-upx.outputs.cache-hit != 'true' }} + run: | + $arch = if (("${{ runner.arch }}" -eq "amd64") -or ("${{ runner.arch }}" -eq "X64")) { "win64" } else { "win32" } + $upxVersion = "${{ env.UPXVERSION }}" + $upxUrl = "https://github.com/upx/upx/releases/download/v$upxVersion/upx-$upxVersion-$arch.zip" + + Invoke-WebRequest -Uri $upxUrl -OutFile upx.zip + Expand-Archive -Path upx.zip -DestinationPath ./upx -Force + + # Windows 版本的 UPX 解压后在子目录中,需要移动到根目录 + Move-Item -Path "./upx/upx-$upxVersion-$arch/*" -Destination ./upx -Force + + shell: pwsh + + - name: Verify UPX installation run: | - mkdir upx - curl -o upx/upx.exe https://assets.ksable.top/github/upx/upx/v5.0.1/windows-amd64/upx.exe + ./upx/upx --version + shell: bash - name: get pip cache dir id: pip-cache-dir From baf984c78a77378a2022181a6658f5683aa12356 Mon Sep 17 00:00:00 2001 From: Kissablecho Date: Wed, 9 Jul 2025 14:17:27 +0800 Subject: [PATCH 18/27] Nuitka Package and Upload(dev) fix value --- .github/workflows/dev_package_and_upload.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dev_package_and_upload.yml b/.github/workflows/dev_package_and_upload.yml index cbd55e2..2f97353 100644 --- a/.github/workflows/dev_package_and_upload.yml +++ b/.github/workflows/dev_package_and_upload.yml @@ -54,7 +54,7 @@ jobs: uses: actions/cache@v4 with: path: upx - key: ${{ runner.os }}-${{ runner.arch }}-upx-v${{ UPXVERSION }} + key: ${{ runner.os }}-${{ runner.arch }}-upx-v${{ env.UPXVERSION }} restore-keys: | ${{ runner.os }}-${{ runner.arch }}-upx- @@ -74,7 +74,7 @@ jobs: ;; esac - UPX_VERSION=${{ UPXVERSION}} + UPX_VERSION=${{ env.UPXVERSION }} UPX_URL="https://github.com/upx/upx/releases/download/v${UPX_VERSION}/upx-${UPX_VERSION}-linux-${UPX_ARCH}.tar.xz" curl -L "$UPX_URL" -o upx.tar.xz From 8ab54fcea12a42056ed0ba724c4c8ee70c735b51 Mon Sep 17 00:00:00 2001 From: Kissablecho Date: Wed, 9 Jul 2025 14:23:09 +0800 Subject: [PATCH 19/27] Nuitka Package and Upload(dev) fix Timezone --- .github/workflows/dev_package_and_upload.yml | 31 +++++++++++++++----- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/.github/workflows/dev_package_and_upload.yml b/.github/workflows/dev_package_and_upload.yml index 2f97353..4d8ec40 100644 --- a/.github/workflows/dev_package_and_upload.yml +++ b/.github/workflows/dev_package_and_upload.yml @@ -35,13 +35,18 @@ jobs: contents: write # 允许创建发布和上传资源 steps: - - name: Set Timezone to China Standard Time - run: tzutil /s "China Standard Time" - shell: pwsh - name: Checkout code uses: actions/checkout@v4 + - name: Set Timezone to China Standard Time on Windows + if: ${{ runner.os == 'Windows' }} + run: tzutil /s "China Standard Time" + shell: pwsh + + - name: Set Timezone to China Standard Time on Linux + if: ${{ runner.os == 'Linux' }} + run: sudo timedatectl set-timezone Asia/Shanghai - name: Set up Python @@ -144,8 +149,8 @@ jobs: nuitka-${{ runner.os }}-${{ runner.arch }}-python-${{ env.PYTHON_VERSION }}- nuitka-${{ runner.os }}-${{ runner.arch }}- - - name: Run packaging script - if: ${{ !github.event.inputs.test }} + - name: Run packaging script on Windows + if: ${{ !github.event.inputs.test && runner.os == 'Windows' }} run: | # 设置Python使用UTF-8编码 [System.Environment]::SetEnvironmentVariable('PYTHONUTF8', '1', 'Process') @@ -154,8 +159,8 @@ jobs: cd package python nuitka_build.py nuitka_config.yml - - name: Run Test packaging script - if: ${{ github.event.inputs.test }} + - name: Run Test packaging script on Windows + if: ${{ github.event.inputs.test && runner.os == 'Windows' }} run: | # 设置Python使用UTF-8编码 [System.Environment]::SetEnvironmentVariable('PYTHONUTF8', '1', 'Process') @@ -164,6 +169,18 @@ jobs: cd package python nuitka_build.py ${{ github.event.inputs.config_path }} + - name: Run packaging script on Windows + if: ${{ !github.event.inputs.test && runner.os == 'Linux' }} + run: | + cd package + python nuitka_build.py nuitka_config.yml + + - name: Run Test packaging script on Windows + if: ${{ github.event.inputs.test && runner.os == 'Linux' }} + run: | + cd package + python nuitka_build.py ${{ github.event.inputs.config_path }} + - name: Upload files with wildcards uses: actions/upload-artifact@v4 with: From b4133b44a01bf5e7db74100fbd2ab80029397523 Mon Sep 17 00:00:00 2001 From: God-2077 Date: Wed, 9 Jul 2025 15:18:03 +0800 Subject: [PATCH 20/27] update --- .github/workflows/dev_package_and_upload.yml | 36 +++++++++----------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/.github/workflows/dev_package_and_upload.yml b/.github/workflows/dev_package_and_upload.yml index 4d8ec40..12458d2 100644 --- a/.github/workflows/dev_package_and_upload.yml +++ b/.github/workflows/dev_package_and_upload.yml @@ -70,18 +70,8 @@ jobs: - name: Install UPX on Linux if: ${{ runner.os == 'Linux' && steps.cache-upx.outputs.cache-hit != 'true' }} run: | - case "${{ runner.arch }}" in - amd64) - UPX_ARCH=x86_64 - ;; - arm64) - UPX_ARCH=aarch64 - ;; - esac - - UPX_VERSION=${{ env.UPXVERSION }} - UPX_URL="https://github.com/upx/upx/releases/download/v${UPX_VERSION}/upx-${UPX_VERSION}-linux-${UPX_ARCH}.tar.xz" + UPX_URL="https://github.com/upx/upx/releases/download/v${{ env.UPXVERSION }}/upx-${{ env.UPXVERSION }}-${{ runner.arch == 'X64' && 'amd64' || 'arm64' }}_linux.tar.xz" curl -L "$UPX_URL" -o upx.tar.xz tar -xf upx.tar.xz -C ./upx --strip-components=1 chmod +x ./upx/upx @@ -107,19 +97,25 @@ jobs: run: | ./upx/upx --version shell: bash - - - name: get pip cache dir - id: pip-cache-dir - run: echo "pip-cache-dir=$(pip cache dir)" >> $env:GITHUB_OUTPUT + - name: get pip cache dir on Windows + if: ${{ runner.os == 'Windows' }} + id: pip-cache-dir-window + run: echo "pip-cache-dir=$(pip cache dir)" >> $env:GITHUB_OUTPUT + + - name: get pip cache dir on Linux + if: ${{ runner.os == 'Linux' }} + id: pip-cache-dir-linux + run: echo "pip-cache-dir=$(pip cache dir)" >> $GITHUB_OUTPUT + - name: pip cache uses: actions/cache@v4 with: - path: ${{ steps.pip-cache-dir.outputs.pip-cache-dir }} # pip缓存路径 - key: ${{ runner.os }}-${{ runner.arch }}-pip-${{ hashFiles('package/nuitka_build.py') }} + path: ${{ runner.os == 'Windows' && steps.pip-cache-dir-window.outputs.pip-cache-dir || steps.pip-cache-dir-linux.outputs.pip-cache-dir }} + key: ${{ runner.os }}-${{ runner.arch }}-pip-${{ github.event.inputs.test && hashFiles(github.event.inputs.config_path) || hashFiles('package/nuitka_build.py') }} restore-keys: | - ${{ runner.os }}-${{ runner.arch }}-pip- # 后备恢复键(当精确键不存在时,使用最近的缓存) - + ${{ runner.os }}-${{ runner.arch }}-pip- + - name: Install dependencies run: | @@ -144,7 +140,7 @@ jobs: uses: actions/cache@v4 with: path: ${{ env.NUITKA_CACHE_DIR }} - key: nuitka-${{ runner.os }}-${{ runner.arch }}-python-${{ env.PYTHON_VERSION }}-nuitka-${{ hashFiles('package/nuitka_build.py') }} + key: nuitka-${{ runner.os }}-${{ runner.arch }}-python-${{ env.PYTHON_VERSION }}-nuitka-${{ github.event.inputs.test && hashFiles(github.event.inputs.config_path) || hashFiles('package/nuitka_build.py') }} restore-keys: | nuitka-${{ runner.os }}-${{ runner.arch }}-python-${{ env.PYTHON_VERSION }}- nuitka-${{ runner.os }}-${{ runner.arch }}- From 5567aa99fa7e3190e589cf591be29058423b3c5f Mon Sep 17 00:00:00 2001 From: God-2077 Date: Wed, 9 Jul 2025 16:46:28 +0800 Subject: [PATCH 21/27] =?UTF-8?q?update=20nuitka=20=E5=85=BC=E5=AE=B9Linux?= =?UTF-8?q?=20Windows=E5=B9=B3=E5=8F=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package/nuitka_build.py | 200 +++++++++++++++++---------------- package/nuitka_test_config.yml | 4 +- 2 files changed, 103 insertions(+), 101 deletions(-) diff --git a/package/nuitka_build.py b/package/nuitka_build.py index 49f0cd1..c143c76 100644 --- a/package/nuitka_build.py +++ b/package/nuitka_build.py @@ -5,10 +5,13 @@ import platform import argparse from pathlib import Path -# from zip import zip_files_and_folders import uuid import shutil +def normalize_path(path_str): + """将路径字符串中的反斜杠转换为当前系统的分隔符""" + return Path(path_str.replace('\\', os.sep)) + def main(): print("="*50) print("="*50) @@ -21,10 +24,10 @@ def main(): print("错误: 请使用Python 3.7或更高版本") return - Machine = platform.system() - arrch = platform.machine() + system_os = platform.system() + arch = platform.machine() - print(f"当前操作系统: {Machine} {arrch}") + print(f"当前操作系统: {system_os} {arch}") print(f"平台详情: {platform.platform()}") print("CPU核心数:", os.cpu_count()) print(f"Python版本: {sys.version}") @@ -35,19 +38,21 @@ def main(): args = parser.parse_args() # 基础路径设置 - base_dir = Path(__file__).parent.parent # 项目根目录 - upx_dir = base_dir / './upx/' # UPX目录 + base_dir = Path(__file__).resolve().parent.parent # 项目根目录 + upx_dir = base_dir / 'upx' # UPX目录 # 读取配置文件 config_path = base_dir / args.config if not config_path.exists(): print(f"错误: 配置文件不存在 {config_path}") sys.exit(1) - with open(str(config_path), 'r', encoding='utf-8') as f: + + with config_path.open('r', encoding='utf-8') as f: config = yaml.safe_load(f) success_count = 0 task_error_list = [] + # 遍历所有打包任务 for i, task in enumerate(config, start=1): try: @@ -55,143 +60,140 @@ def main(): print(f"开始打包任务: [{i}/{len(config)}] {task['name']}") print(f"{'='*40}") - # 解析任务参数 - python_file = base_dir / task['python-file'] - dist_path = base_dir / task['distpath'] + # 解析任务参数 - 使用路径规范化 + python_file = base_dir / normalize_path(task['python-file']) + dist_path = base_dir / normalize_path(task['distpath']) requirements = task.get('install-requirements', []) enable_plugins = task.get('enable-plugins', []) - # onefile = task.get('onefile', 0) icon = task.get('icon') windows_disable_console = task.get('windows-disable-console', False) name = task.get('name') version = task.get('version') timeout = task.get('timeout', 60 * 45) - output_name_template = task.get('output-name-template', '{{name}}_{{version}}_nuitka_{{os}}_{{arch}}') - if arrch == "AMD64": - arrch = "x64" - output_name = output_name_template.replace('{{name}}', name).replace('{{version}}', version).replace('{{arch}}', arrch).replace('{{os}}', Machine) + + # 处理输出文件名模板 + output_name_template = task.get('output-name-template', '{{name}}_{{version}}_nuitka_{{os}}_{{arch}}{{exe_suffix}}') + + # 处理架构名称统一 + normalized_arch = "x64" if arch == "AMD64" else arch + exe_suffix = '.exe' if system_os == 'Windows' else '' + + output_name = output_name_template.replace('{{name}}', name) \ + .replace('{{version}}', version) \ + .replace('{{arch}}', normalized_arch) \ + .replace('{{os}}', system_os) \ + .replace('{{exe_suffix}}', exe_suffix) + custom_command = task.get('custom-command') - # 检查操作系统和架构 - # if Machine not in task.get('os', []): - # print(f"警告: 任务 [{i}/{len(config)} {task['name']}] 不支持当前操作系统 {Machine}") - # continue - # if arrch not in task.get('arch', []): - # print(f"警告: 任务 [{i}/{len(config)} {task['name']}] 不支持当前架构 {arrch}") - # continue # 检查Python文件是否存在 if not python_file.exists(): print(f"错误: Python文件不存在 {python_file}") continue + # 创建输出目录 + dist_path.mkdir(parents=True, exist_ok=True) + # 安装依赖 if requirements: print(f"安装依赖: {', '.join(requirements)}") subprocess.run([sys.executable, '-m', 'pip', 'install'] + requirements, check=True) - # 构建PyInstaller命令 + # 构建Nuitka命令 cmd = [ sys.executable, '-m', 'nuitka', - f'--output-filename={output_name}.exe', - f'--output-dir={dist_path}', # 输出目录 - '--onefile', # 单文件 + f'--output-filename={output_name}', + f'--output-dir={dist_path}', # 输出目录 + '--onefile', # 单文件 '--standalone', - '--mingw64', - f'--jobs={os.cpu_count()}', # 多线程 - # '--mode', - '--assume-yes-for-downloads', #自动下载外部代码 - # '--show-memory' - + f'--jobs={os.cpu_count()}', # 多线程 + '--assume-yes-for-downloads', # 自动下载外部代码 ] - # 添加窗口模式选项 - if windows_disable_console: - cmd.append('--windows-disable-console') - - # 添加图标选项 - if icon: - icon_path = base_dir / icon - if icon_path.exists(): - cmd.append(f'--windows-icon-from-ico={str(icon_path)}') - else: - print(f"警告: 图标文件不存在 {icon_path}") - - - # if arrch == "ARM64": - # print("UPX不支持当前架构") - # else: - # if use_upx: - # if upx_dir.exists(): - # cmd.append('--plugin-enable=upx') - # cmd.append(f'--upx-binary={str(upx_dir)}') - # print(f"使用UPX压缩: {upx_dir}") - # else: - # print(f"警告: UPX目录不存在 {upx_dir}") - # else: - # print("不使用UPX压缩") + # Windows特定参数 + if system_os == 'Windows': + cmd.append('--mingw64') + if windows_disable_console: + cmd.append('--windows-disable-console') + + if icon: + icon_path = base_dir / normalize_path(icon) + if icon_path.exists(): + cmd.append(f'--windows-icon-from-ico={icon_path}') + else: + print(f"警告: 图标文件不存在 {icon_path}") + else: + # Linux/macOS 使用 clang + cmd.append('--clang') + # 启用插件 if enable_plugins: - plugin_list = '' - if len(enable_plugins) == 1: - plugin_list = enable_plugins[0] - else: - plugin_list = ','.join(enable_plugins) + plugin_list = ','.join(enable_plugins) cmd.append(f'--plugin-enable={plugin_list}') + + # UPX处理 if 'upx' in enable_plugins: - if upx_dir.exists(): - cmd.append(f'--upx-binary={str(upx_dir)}') - print(f"使用UPX压缩: {upx_dir}") + upx_exe = 'upx.exe' if system_os == 'Windows' else 'upx' + upx_path = upx_dir / upx_exe + + if upx_path.exists(): + cmd.append(f'--upx-binary={upx_path}') + print(f"使用UPX压缩: {upx_path}") else: - print(f"警告: UPX目录不存在 {upx_dir}") + print(f"警告: UPX可执行文件不存在 {upx_path}") + # 添加自定义命令 if custom_command: - # custom_command 为 str if isinstance(custom_command, str): cmd.extend(custom_command.split()) - # custom_command 为 list elif isinstance(custom_command, list): cmd.extend(custom_command) - - # 避免中文等特殊字符导致编译报错 - t_file = str(uuid.uuid4()) + ".py" - t_file_path = base_dir / t_file - shutil.copy(str(python_file), t_file_path) - cmd.append(str(t_file_path)) + + # 创建临时文件避免中文路径问题 + temp_file = base_dir / f"{uuid.uuid4().hex}.py" + shutil.copy(python_file, temp_file) + cmd.append(str(temp_file)) # 打印并执行命令 print("执行命令:", ' '.join(cmd)) - if timeout: - try: - result = subprocess.run(cmd,timeout=timeout) - except subprocess.TimeoutExpired: - print(f"任务[{i}/{len(config)} {task['name']}] 执行超时 {timeout} 秒") - print(f"任务[{i}/{len(config)} {task['name']}]失败: {e}") - os.remove(t_file_path) - task_error_list.append(task['name']) - continue - else: - result = subprocess.run(cmd) - if result.returncode == 0: + try: + # 执行打包命令 + result = subprocess.run( + cmd, + timeout=timeout, + check=True + ) + print(f"打包成功: {dist_path / output_name}") - os.remove(t_file_path) success_count += 1 - else: - print(f"打包失败,退出码: {result.returncode}") - os.remove(t_file_path) + + except subprocess.TimeoutExpired: + print(f"任务[{i}/{len(config)} {task['name']}] 执行超时 {timeout} 秒") + task_error_list.append(task['name']) + except subprocess.CalledProcessError as e: + print(f"打包失败,退出码: {e.returncode}") + print(f"错误输出: {e.stderr}") + task_error_list.append(task['name']) + finally: + # 确保临时文件被删除 + if temp_file.exists(): + temp_file.unlink() + except Exception as e: - print(f"任务[{i}/{len(config)} {task['name']}]失败: {e}") + print(f"任务[{i}/{len(config)} {task['name']}]失败: {str(e)}") + import traceback + traceback.print_exc() task_error_list.append(task['name']) - continue - if success_count != 0: - print(f"打包完成,成功打包 [{success_count}/{len(config)}] 个任务") - if task_error_list != []: - print(f"打包失败的任务: {', '.join(task_error_list)}") - else: - print("打包失败,没有成功打包任何任务") + + # 输出最终结果 + print("\n" + "="*50) + print(f"打包完成: 成功 {success_count} 个, 失败 {len(task_error_list)} 个") + + if task_error_list: print(f"失败的任务: {', '.join(task_error_list)}") sys.exit(1) if __name__ == '__main__': - main() + main() \ No newline at end of file diff --git a/package/nuitka_test_config.yml b/package/nuitka_test_config.yml index 9306565..e17be43 100644 --- a/package/nuitka_test_config.yml +++ b/package/nuitka_test_config.yml @@ -1,6 +1,6 @@ - name: 'hello_world' version: 'v.25.07.08' - python-file: 'package\hello_world.py' + python-file: 'package/hello_world.py' install-requirements: [ 'psutil' ] @@ -8,7 +8,7 @@ 'upx' ] # onefile: 2 # 0:文件夹 1:单文件 2:两者 - icon: package\assets\favicon.ico + icon: package/assets/favicon.ico windows-disable-console: False distpath: 'dist' timeout: 2700 From c2404a424854387022b47b24423c3e623fdb1c1b Mon Sep 17 00:00:00 2001 From: God-2077 Date: Wed, 9 Jul 2025 16:56:28 +0800 Subject: [PATCH 22/27] remove windows-11-arm --- .github/workflows/dev_package_and_upload.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev_package_and_upload.yml b/.github/workflows/dev_package_and_upload.yml index 12458d2..3ccdee9 100644 --- a/.github/workflows/dev_package_and_upload.yml +++ b/.github/workflows/dev_package_and_upload.yml @@ -24,7 +24,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [ubuntu-latest, ubuntu-24.04-arm, windows-latest, windows-11-arm] + os: [ubuntu-latest,ubuntu-24.04-arm,windows-latest] # windows-11-arm没有对应的 Python env: PYTHON_VERSION: '3.10' NUITKA_CACHE_DIR: ${{ github.workspace }}/nuitka-cache From 0b65153aed7f649a8c017f4f8933f9903aa105fa Mon Sep 17 00:00:00 2001 From: Kissablecho Date: Wed, 9 Jul 2025 18:18:22 +0800 Subject: [PATCH 23/27] update --- .github/workflows/dev_package_and_upload.yml | 2 +- package/nuitka_build.py | 18 +++++++++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dev_package_and_upload.yml b/.github/workflows/dev_package_and_upload.yml index 3ccdee9..3e759d5 100644 --- a/.github/workflows/dev_package_and_upload.yml +++ b/.github/workflows/dev_package_and_upload.yml @@ -182,7 +182,7 @@ jobs: with: name: ${{ runner.os }}-${{ runner.arch }}-${{ github.event.inputs.test && 'test-' || '' }}artifact path: | - ./dist/*.exe + ./dist/* retention-days: 14 if-no-files-found: warn overwrite: true diff --git a/package/nuitka_build.py b/package/nuitka_build.py index c143c76..8588647 100644 --- a/package/nuitka_build.py +++ b/package/nuitka_build.py @@ -27,9 +27,11 @@ def main(): system_os = platform.system() arch = platform.machine() - print(f"当前操作系统: {system_os} {arch}") + print(f"当前操作系统: {system_os}") + print(f'架构: {arch}') print(f"平台详情: {platform.platform()}") print("CPU核心数:", os.cpu_count()) + print("处理器信息:", platform.processor()) print(f"Python版本: {sys.version}") # 解析命令行参数 @@ -190,6 +192,20 @@ def main(): # 输出最终结果 print("\n" + "="*50) print(f"打包完成: 成功 {success_count} 个, 失败 {len(task_error_list)} 个") + + if success_count != 0: + files_list = [] + + # 遍历目录下的所有条目 + for entry in os.listdir(str(base_dir / 'dist')): + # 拼接完整的文件路径 + full_path = os.path.join(str(base_dir / 'dist'), entry) + # 检查该路径是否为文件 + if os.path.isfile(full_path): + files_list.append(entry) + + # 输出文件列表 + print(f'Dist: {str(files_list)}') if task_error_list: print(f"失败的任务: {', '.join(task_error_list)}") From 367ca79140afccfd491a7a606a6d9ac27cdb0275 Mon Sep 17 00:00:00 2001 From: Kissablecho Date: Wed, 9 Jul 2025 21:22:23 +0800 Subject: [PATCH 24/27] more option --- package/nuitka_build.py | 14 ++++++++++++++ package/nuitka_test_config.yml | 4 ++++ 2 files changed, 18 insertions(+) diff --git a/package/nuitka_build.py b/package/nuitka_build.py index 8588647..79bb4f6 100644 --- a/package/nuitka_build.py +++ b/package/nuitka_build.py @@ -88,6 +88,8 @@ def main(): .replace('{{exe_suffix}}', exe_suffix) custom_command = task.get('custom-command') + only_linux_command = task.get('only-linux-command') + only_windows_command = task.get('only-windows-command') # 检查Python文件是否存在 if not python_file.exists(): @@ -125,6 +127,18 @@ def main(): cmd.append(f'--windows-icon-from-ico={icon_path}') else: print(f"警告: 图标文件不存在 {icon_path}") + if only_windows_command: + if isinstance(only_windows_command, str): + cmd.extend(only_windows_command.split()) + elif isinstance(only_windows_command, list): + cmd.extend(only_windows_command) + elif system_os == 'Linux': + if only_linux_command: + if isinstance(only_linux_command, str): + cmd.extend(only_linux_command.split()) + elif isinstance(only_linux_command, list): + cmd.extend(only_linux_command) + cmd.append('--clang') else: # Linux/macOS 使用 clang cmd.append('--clang') diff --git a/package/nuitka_test_config.yml b/package/nuitka_test_config.yml index e17be43..d76b77d 100644 --- a/package/nuitka_test_config.yml +++ b/package/nuitka_test_config.yml @@ -14,3 +14,7 @@ timeout: 2700 output-name-template: '{{name}}_{{version}}_nuitka_{{os}}_{{arch}}' custom-command: [] + only-linux-command: [ + '--static-libpython=yes' # 使用静态链接,减少对系统库的依赖 + ] + only-windows-command: [] From 077c594a9a8942cb25244eea2dad8183b43b5c0c Mon Sep 17 00:00:00 2001 From: Kissablecho Date: Wed, 9 Jul 2025 22:37:09 +0800 Subject: [PATCH 25/27] fix artifact upload --- package/nuitka_build.py | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/package/nuitka_build.py b/package/nuitka_build.py index 79bb4f6..4c121ea 100644 --- a/package/nuitka_build.py +++ b/package/nuitka_build.py @@ -12,6 +12,36 @@ def normalize_path(path_str): """将路径字符串中的反斜杠转换为当前系统的分隔符""" return Path(path_str.replace('\\', os.sep)) +def delete_folders(directory): + """删除指定目录下的所有文件夹,但保留文件""" + if os.path.basename(directory) == '' or os.path.basename(directory): + dir_name = os.path.basename(os.path.dirname(directory)) + else: + dir_name = os.path.basename(directory) + print(f'清理文件夹({dir_name})下的文件夹') + try: + # 确保目录存在 + if not os.path.exists(directory): + print(f"目录不存在: {directory}") + return True + + # 遍历目录中的所有项 + for item in os.listdir(directory): + item_path = os.path.join(directory, item) + # 如果是文件夹,则删除 + if os.path.isdir(item_path): + # print(f"删除文件夹: {item_path}") + rm_item_dir = ','.join(item_path) + shutil.rmtree(item_path) + # else: + # print(f"保留文件: {item_path}") + print(f'清理文件夹({dir_name})下的文件夹完成: {rm_item_dir}') + print("操作完成") + return True + except Exception as e: + print(f"发生错误: {e}") + return False + def main(): print("="*50) print("="*50) @@ -42,7 +72,7 @@ def main(): # 基础路径设置 base_dir = Path(__file__).resolve().parent.parent # 项目根目录 upx_dir = base_dir / 'upx' # UPX目录 - + dist_path = base_dir / 'dist' # 读取配置文件 config_path = base_dir / args.config if not config_path.exists(): @@ -64,7 +94,7 @@ def main(): # 解析任务参数 - 使用路径规范化 python_file = base_dir / normalize_path(task['python-file']) - dist_path = base_dir / normalize_path(task['distpath']) + # dist_path = base_dir / normalize_path(task['distpath']) requirements = task.get('install-requirements', []) enable_plugins = task.get('enable-plugins', []) @@ -220,6 +250,9 @@ def main(): # 输出文件列表 print(f'Dist: {str(files_list)}') + # 清理文件夹 + if delete_folders(dist_path): + print(f"已清理dist目录下文件夹: {dist_path}") if task_error_list: print(f"失败的任务: {', '.join(task_error_list)}") From cb08bea5d1f64f4a9ef13a5f386de20b4d1a4208 Mon Sep 17 00:00:00 2001 From: Kissablecho Date: Wed, 9 Jul 2025 23:25:42 +0800 Subject: [PATCH 26/27] update Package --- .github/workflows/dev_package_and_upload.yml | 22 +-- .github/workflows/nuitka_package_release.yml | 143 ++++++++++++++++--- package/nuitka_build.py | 4 +- package/nuitka_config.yml | 30 ++-- package/nuitka_test_config.yml | 4 +- 5 files changed, 158 insertions(+), 45 deletions(-) diff --git a/.github/workflows/dev_package_and_upload.yml b/.github/workflows/dev_package_and_upload.yml index 3e759d5..1252b40 100644 --- a/.github/workflows/dev_package_and_upload.yml +++ b/.github/workflows/dev_package_and_upload.yml @@ -135,6 +135,12 @@ jobs: # [System.Environment]::SetEnvironmentVariable('PYTHONUTF8', '1', 'Process') # # 设置控制台编码为UTF-8 # chcp.com 65001 + + - name: Install ccache on Linux + if: ${{ runner.os == 'Linux' }} + run: | + sudo apt-get update -y + sudo apt-get install -y ccache - name: Cache Nuitka cache directory uses: actions/cache@v4 @@ -152,8 +158,7 @@ jobs: [System.Environment]::SetEnvironmentVariable('PYTHONUTF8', '1', 'Process') # 设置控制台编码为UTF-8 chcp.com 65001 - cd package - python nuitka_build.py nuitka_config.yml + python ./package/nuitka_build.py ./package/nuitka_config.yml - name: Run Test packaging script on Windows if: ${{ github.event.inputs.test && runner.os == 'Windows' }} @@ -162,20 +167,17 @@ jobs: [System.Environment]::SetEnvironmentVariable('PYTHONUTF8', '1', 'Process') # 设置控制台编码为UTF-8 chcp.com 65001 - cd package - python nuitka_build.py ${{ github.event.inputs.config_path }} + python ./package/nuitka_build.py ${{ github.event.inputs.config_path }} - - name: Run packaging script on Windows + - name: Run packaging script on Linux if: ${{ !github.event.inputs.test && runner.os == 'Linux' }} run: | - cd package - python nuitka_build.py nuitka_config.yml + python ./package/nuitka_build.py ./package/nuitka_config.yml - - name: Run Test packaging script on Windows + - name: Run Test packaging script on Linux if: ${{ github.event.inputs.test && runner.os == 'Linux' }} run: | - cd package - python nuitka_build.py ${{ github.event.inputs.config_path }} + python ./package/nuitka_build.py ${{ github.event.inputs.config_path }} - name: Upload files with wildcards uses: actions/upload-artifact@v4 diff --git a/.github/workflows/nuitka_package_release.yml b/.github/workflows/nuitka_package_release.yml index 490faf2..7b4fb95 100644 --- a/.github/workflows/nuitka_package_release.yml +++ b/.github/workflows/nuitka_package_release.yml @@ -1,4 +1,4 @@ -name: Nuitka Package and Release +name: Nuitka Package and Upload(dev) on: workflow_dispatch: @@ -9,41 +9,122 @@ on: - 'package/nuitka_config.yml' jobs: - package-and-release: + package-and-upload: runs-on: windows-latest + # runs-on: ${{ matrix.os }} + # strategy: + # matrix: + # os: [ubuntu-latest,ubuntu-24.04-arm,windows-latest] # windows-11-arm没有对应的 Python + env: + PYTHON_VERSION: '3.10' + NUITKA_CACHE_DIR: ${{ github.workspace }}/nuitka-cache + UPXVERSION: '5.0.1' # 添加必要的权限 permissions: contents: write # 允许创建发布和上传资源 steps: - - name: Set Timezone to China Standard Time - run: tzutil /s "China Standard Time" - shell: pwsh - name: Checkout code uses: actions/checkout@v4 - - name: Generate version tag - id: version + - name: Set Timezone to China Standard Time on Windows + if: ${{ runner.os == 'Windows' }} + run: tzutil /s "China Standard Time" + shell: pwsh + + - name: Set Timezone to China Standard Time on Linux + if: ${{ runner.os == 'Linux' }} + run: sudo timedatectl set-timezone Asia/Shanghai + + - name: Generate version tag on Windows + if: ${{ runner.os == 'Windows' }} run: | # 使用 UTC 时间确保一致性 $date = (Get-Date).ToUniversalTime().ToString("yy.MM.dd") $tag = "v$date" $release = "Release $date" - echo "tag=$tag" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append - echo "release_name=$release" | Out-File -FilePath $env:GITHUB_OUTPUT -Encoding utf8 -Append - - + echo "VERSION_TAG=$tag" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append + echo "RELEASE_NAME=$release" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append + shell: pwsh + + - name: Generate version tag on Linux + if: ${{ runner.os == 'Linux' }} + run: | + # 使用 UTC 时间确保一致性 + DATE=$(date -u +%y.%m.%d) + echo "VERSION_TAG=v$DATE" >> $GITHUB_ENV + echo "RELEASE_NAME=Release $DATE" >> $GITHUB_ENV + shell: bash + - name: Set up Python uses: actions/setup-python@v5 with: - python-version: '3.10' + python-version: ${{ env.PYTHON_VERSION }} + + - name: Cache UPX + id: cache-upx + uses: actions/cache@v4 + with: + path: upx + key: ${{ runner.os }}-${{ runner.arch }}-upx-v${{ env.UPXVERSION }} + restore-keys: | + ${{ runner.os }}-${{ runner.arch }}-upx- + + - name: Create UPX directory + if: ${{ steps.cache-upx.outputs.cache-hit != 'true' }} + run: mkdir -p ./upx + + - name: Install UPX on Linux + if: ${{ runner.os == 'Linux' && steps.cache-upx.outputs.cache-hit != 'true' }} + run: | + + UPX_URL="https://github.com/upx/upx/releases/download/v${{ env.UPXVERSION }}/upx-${{ env.UPXVERSION }}-${{ runner.arch == 'X64' && 'amd64' || 'arm64' }}_linux.tar.xz" + curl -L "$UPX_URL" -o upx.tar.xz + tar -xf upx.tar.xz -C ./upx --strip-components=1 + chmod +x ./upx/upx + + shell: bash - - name: UPX Setup + - name: Install UPX on Windows + if: ${{ runner.os == 'Windows' && steps.cache-upx.outputs.cache-hit != 'true' }} run: | - mkdir upx - curl -o upx/upx.exe https://assets.ksable.top/github/upx/upx/v5.0.1/windows-amd64/upx.exe + $arch = if (("${{ runner.arch }}" -eq "amd64") -or ("${{ runner.arch }}" -eq "X64")) { "win64" } else { "win32" } + $upxVersion = "${{ env.UPXVERSION }}" + $upxUrl = "https://github.com/upx/upx/releases/download/v$upxVersion/upx-$upxVersion-$arch.zip" + + Invoke-WebRequest -Uri $upxUrl -OutFile upx.zip + Expand-Archive -Path upx.zip -DestinationPath ./upx -Force + + # Windows 版本的 UPX 解压后在子目录中,需要移动到根目录 + Move-Item -Path "./upx/upx-$upxVersion-$arch/*" -Destination ./upx -Force + + shell: pwsh + + - name: Verify UPX installation + run: | + ./upx/upx --version + shell: bash + + - name: get pip cache dir on Windows + if: ${{ runner.os == 'Windows' }} + id: pip-cache-dir-window + run: echo "pip-cache-dir=$(pip cache dir)" >> $env:GITHUB_OUTPUT + + - name: get pip cache dir on Linux + if: ${{ runner.os == 'Linux' }} + id: pip-cache-dir-linux + run: echo "pip-cache-dir=$(pip cache dir)" >> $GITHUB_OUTPUT + + - name: pip cache + uses: actions/cache@v4 + with: + path: ${{ runner.os == 'Windows' && steps.pip-cache-dir-window.outputs.pip-cache-dir || steps.pip-cache-dir-linux.outputs.pip-cache-dir }} + key: ${{ runner.os }}-${{ runner.arch }}-pip-${{ github.event.inputs.test && hashFiles(github.event.inputs.config_path) || hashFiles('package/nuitka_build.py') }} + restore-keys: | + ${{ runner.os }}-${{ runner.arch }}-pip- + - name: Install dependencies run: | @@ -64,14 +145,34 @@ jobs: # # 设置控制台编码为UTF-8 # chcp.com 65001 - - name: Run packaging script + - name: Install ccache on Linux + if: ${{ runner.os == 'Linux' }} + run: | + sudo apt-get update -y + sudo apt-get install -y ccache + + - name: Cache Nuitka cache directory + uses: actions/cache@v4 + with: + path: ${{ env.NUITKA_CACHE_DIR }} + key: nuitka-${{ runner.os }}-${{ runner.arch }}-python-${{ env.PYTHON_VERSION }}-nuitka-${{ github.event.inputs.test && hashFiles(github.event.inputs.config_path) || hashFiles('package/nuitka_build.py') }} + restore-keys: | + nuitka-${{ runner.os }}-${{ runner.arch }}-python-${{ env.PYTHON_VERSION }}- + nuitka-${{ runner.os }}-${{ runner.arch }}- + + - name: Run packaging script on Windows + if: ${{ runner.os == 'Windows' }} run: | # 设置Python使用UTF-8编码 [System.Environment]::SetEnvironmentVariable('PYTHONUTF8', '1', 'Process') # 设置控制台编码为UTF-8 chcp.com 65001 - cd package - python nuitka_build.py nuitka_config.yml + python ./package/nuitka_build.py ./package/nuitka_config.yml + + - name: Run packaging script on Linux + if: ${{ runner.os == 'Linux' }} + run: | + python ./package/nuitka_build.py ./package/nuitka_config.yml - name: Create Release id: create_release @@ -79,11 +180,11 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: - tag_name: ${{ steps.version.outputs.tag }} - name: ${{ steps.version.outputs.release_name }} + tag_name: ${{ env.VERSION_TAG }} + name: ${{ env.RELEASE_NAME }} generate_release_notes: true draft: false prerelease: false overwrite_files: true files: | - dist/*.exe + dist/* diff --git a/package/nuitka_build.py b/package/nuitka_build.py index 4c121ea..3854918 100644 --- a/package/nuitka_build.py +++ b/package/nuitka_build.py @@ -63,6 +63,7 @@ def main(): print("CPU核心数:", os.cpu_count()) print("处理器信息:", platform.processor()) print(f"Python版本: {sys.version}") + print(f'工作目录: {os.getcwd()}') # 解析命令行参数 parser = argparse.ArgumentParser(description='Nuitka打包脚本') @@ -74,7 +75,8 @@ def main(): upx_dir = base_dir / 'upx' # UPX目录 dist_path = base_dir / 'dist' # 读取配置文件 - config_path = base_dir / args.config + # config_path = base_dir / args.config + config_path = args.config if not config_path.exists(): print(f"错误: 配置文件不存在 {config_path}") sys.exit(1) diff --git a/package/nuitka_config.yml b/package/nuitka_config.yml index c77d3fb..b27c113 100644 --- a/package/nuitka_config.yml +++ b/package/nuitka_config.yml @@ -1,6 +1,6 @@ - name: 'novel_crawler' version: 'v.25.07.08' - python-file: 'novel_crawler\novel_crawler_v.25.07.08.py' + python-file: 'novel_crawler/novel_crawler_v.25.07.08.py' install-requirements: [ 'beautifulsoup4', 'requests', @@ -12,16 +12,18 @@ 'upx' ] # onefile: 2 # 0:文件夹 1:单文件 2:两者 - icon: package\assets\favicon.ico + icon: package/assets/favicon.ico windows-disable-console: False distpath: 'dist' timeout: 2700 output-name-template: '{{name}}_{{version}}_nuitka_{{os}}_{{arch}}' custom-command: [] + only-linux-command: [] + only-windows-command: [] - name: 'Keyboard_monitoring' version: 'v.24.07.16' - python-file: '键盘监听\v.24.07.16.py' + python-file: '键盘监听/v.24.07.16.py' install-requirements: [ 'keyboard', 'configparser', @@ -32,16 +34,18 @@ 'upx' ] # onefile: 1 - icon: package\assets\favicon.ico + icon: package/assets/favicon.ico windows-disable-console: False distpath: 'dist' timeout: 2700 output-name-template: '{{name}}_{{version}}_nuitka_{{os}}_{{arch}}' custom-command: [] + only-linux-command: [] + only-windows-command: [] - name: 'NetEase_Cloud_Music_Download' version: 'v.25-07-08' - python-file: '网易云音乐歌单批量下载歌曲\v.25-07-08.py' + python-file: '网易云音乐歌单批量下载歌曲/v.25-07-08.py' install-requirements: [ 'quote', 'requests', @@ -52,16 +56,18 @@ 'upx' ] # onefile: 1 - icon: package\assets\favicon.ico + icon: package/assets/favicon.ico windows-disable-console: False distpath: 'dist' timeout: 2700 output-name-template: '{{name}}_{{version}}_nuitka_{{os}}_{{arch}}' custom-command: [] + only-linux-command: [] + only-windows-command: [] - name: 'ftp_server' version: 'v.25-05-02' - python-file: 'ftp_server\ftp_server_v.25-05-02.py' + python-file: 'ftp_server/ftp_server_v.25-05-02.py' install-requirements: [ 'pyftpdlib' ] @@ -69,16 +75,18 @@ 'upx' ] # onefile: 1 - icon: package\assets\favicon.ico + icon: package/assets/favicon.ico windows-disable-console: False distpath: 'dist' timeout: 2700 output-name-template: '{{name}}_{{version}}_nuitka_{{os}}_{{arch}}' custom-command: [] + only-linux-command: [] + only-windows-command: [] - name: 'sunrise_sunset_info' version: 'v.25.05.02' - python-file: 'sunrise_sunset_info\sunrise_sunset_info_v.25.05.02.py' + python-file: 'sunrise_sunset_info/sunrise_sunset_info_v.25.05.02.py' install-requirements: [ 'pyftpdlib', 'astropy' @@ -87,9 +95,11 @@ 'upx' ] # onefile: 1 # 0:文件夹 1:单文件 2:两者 - icon: package\assets\favicon.ico + icon: package/assets/favicon.ico windows-disable-console: False distpath: 'dist' timeout: 2700 output-name-template: '{{name}}_{{version}}_nuitka_{{os}}_{{arch}}' custom-command: [] + only-linux-command: [] + only-windows-command: [] diff --git a/package/nuitka_test_config.yml b/package/nuitka_test_config.yml index d76b77d..1860375 100644 --- a/package/nuitka_test_config.yml +++ b/package/nuitka_test_config.yml @@ -14,7 +14,5 @@ timeout: 2700 output-name-template: '{{name}}_{{version}}_nuitka_{{os}}_{{arch}}' custom-command: [] - only-linux-command: [ - '--static-libpython=yes' # 使用静态链接,减少对系统库的依赖 - ] + only-linux-command: [] only-windows-command: [] From d9dbaebebd331bc7a964bf841956b41ed786e0bd Mon Sep 17 00:00:00 2001 From: Kissablecho Date: Wed, 9 Jul 2025 23:39:43 +0800 Subject: [PATCH 27/27] fix workflows name and fix nuitka_build.py --- .github/workflows/nuitka_package_release.yml | 2 +- package/nuitka_build.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/nuitka_package_release.yml b/.github/workflows/nuitka_package_release.yml index 7b4fb95..e081768 100644 --- a/.github/workflows/nuitka_package_release.yml +++ b/.github/workflows/nuitka_package_release.yml @@ -1,4 +1,4 @@ -name: Nuitka Package and Upload(dev) +name: Nuitka Package and Release on: workflow_dispatch: diff --git a/package/nuitka_build.py b/package/nuitka_build.py index 3854918..948c98f 100644 --- a/package/nuitka_build.py +++ b/package/nuitka_build.py @@ -76,7 +76,7 @@ def main(): dist_path = base_dir / 'dist' # 读取配置文件 # config_path = base_dir / args.config - config_path = args.config + config_path = Path(args.config) if not config_path.exists(): print(f"错误: 配置文件不存在 {config_path}") sys.exit(1)