dmMaze / BallonsTranslator

深度学习辅助漫画翻译工具, 支持一键机翻和简单的图像/文本编辑 | Yet another computer-aided comic/manga translation tool powered by deeplearning
GNU General Public License v3.0
2.68k stars 179 forks source link

用pyinstaller将本项目打包成standalone macOS app的方法 #58

Closed ghost closed 11 months ago

ghost commented 1 year ago

之前版本能够在M1 Max Mac上启动了,但后来电脑重装了,有些库都变过了,就重新来了一遍,新版本在maxOS上又无法启动了

requirements_macOS.txt 中的cocoa库没有找到,去PyPI也没有,我猜是不是pycocoa?改成pycocoa后requirements_macOS安装成功,然后运行python ballontranslator

报错如下,虽然using pyqt6,但还是提示找不到pyqt5

❯ python ballontranslator
/Users/usr/.pyenv/versions/3.9.12/lib/python3.9/site-packages/qtpy/__init__.py:267: RuntimeWarning: Selected binding "pyqt5" could not be found, using "pyqt6"
  warnings.warn('Selected binding "{}" could not be found, '
Traceback (most recent call last):
  File "/Users/usr/.pyenv/versions/3.9.12/lib/python3.9/runpy.py", line 197, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "/Users/usr/.pyenv/versions/3.9.12/lib/python3.9/runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "/Users/usr/Downloads/BallonsTranslator/ballontranslator/__main__.py", line 60, in <module>
    main()
  File "/Users/usr/Downloads/BallonsTranslator/ballontranslator/__main__.py", line 52, in main
    from ui.mainwindow import MainWindow
  File "/Users/usr/Downloads/BallonsTranslator/ballontranslator/ui/mainwindow.py", line 22, in <module>
    from .mainwindowbars import TitleBar, LeftBar, BottomBar
  File "/Users/usr/Downloads/BallonsTranslator/ballontranslator/ui/mainwindowbars.py", line 11, in <module>
    from .framelesswindow import startSystemMove
  File "/Users/usr/Downloads/BallonsTranslator/ballontranslator/ui/framelesswindow/__init__.py", line 6, in <module>
    from .fw_qt6.utils import startSystemMove
  File "/Users/usr/Downloads/BallonsTranslator/ballontranslator/ui/framelesswindow/fw_qt6/__init__.py", line 8, in <module>
    from .mac import AcrylicWindow
  File "/Users/usr/Downloads/BallonsTranslator/ballontranslator/ui/framelesswindow/fw_qt6/mac/__init__.py", line 8, in <module>
    from .window_effect import MacWindowEffect
  File "/Users/usr/Downloads/BallonsTranslator/ballontranslator/ui/framelesswindow/fw_qt6/mac/window_effect.py", line 5, in <module>
    from ..utils.mac_utils import getNSWindow
  File "/Users/usr/Downloads/BallonsTranslator/ballontranslator/ui/framelesswindow/fw_qt6/utils/__init__.py", line 7, in <module>
    from .mac_utils import MacMoveResize as MoveResize
  File "/Users/usr/Downloads/BallonsTranslator/ballontranslator/ui/framelesswindow/fw_qt6/utils/mac_utils.py", line 6, in <module>
    from PyQt5.QtCore import QT_VERSION_STR
ModuleNotFoundError: No module named 'PyQt5.QtCore'
dmMaze commented 1 year ago

你试下这里try from PyQt5... except: from PyQt6... 一下,如果可以就开个pr,其它类似的异常也一样处理

ghost commented 1 year ago

/BallonsTranslator/ballontranslator/ui/framelesswindow/fw_qt6/utils/mac_utils.py

# coding:utf-8
from ctypes import c_void_p

import Cocoa
import objc
try from PyQt5... except: from PyQt6...

这样吗,还是会报错

dmMaze commented 1 year ago

/BallonsTranslator/ballontranslator/ui/framelesswindow/fw_qt6/utils/mac_utils.py

# coding:utf-8
from ctypes import c_void_p

import Cocoa
import objc
try from PyQt5... except: from PyQt6...

这样吗,还是会报错

哦不用try except, 把这个fw_qt6里面所有的PyQt5都换成PyQt6

ghost commented 1 year ago
❯ python __main__.py
/Users/usr/.pyenv/versions/3.9.12/lib/python3.9/site-packages/qtpy/__init__.py:267: RuntimeWarning: Selected binding "pyqt5" could not be found, using "pyqt6"
  warnings.warn('Selected binding "{}" could not be found, '
[ERROR  ] configpanel:__init__:281 - [Errno 2] No such file or directory: '/Users/usr/Downloads/BallonsTranslator/ballontranslator/data/config/config.json'
Traceback (most recent call last):
  File "/Users/usr/Downloads/BallonsTranslator/ballontranslator/ui/configpanel.py", line 277, in __init__
    with open(CONFIG_PATH, 'r', encoding='utf8') as f:
FileNotFoundError: [Errno 2] No such file or directory: '/Users/usr/Downloads/BallonsTranslator/ballontranslator/data/config/config.json'
[WARNING] configpanel:__init__:282 - Failed to load config file, using default config
[INFO   ] dl_manager:on_finish_setdetector:634 - Text detector set to ctd
[INFO   ] dl_manager:on_finish_settranslator:655 - Translator set to google
[INFO   ] dl_manager:on_finish_setocr:640 - OCR set to mit32px
[INFO   ] dl_manager:on_finish_setinpainter:647 - Inpainter set to lama_mpe

可以启动了,但有提示error,这个有影响吗?

dmMaze commented 1 year ago
❯ python __main__.py
/Users/usr/.pyenv/versions/3.9.12/lib/python3.9/site-packages/qtpy/__init__.py:267: RuntimeWarning: Selected binding "pyqt5" could not be found, using "pyqt6"
  warnings.warn('Selected binding "{}" could not be found, '
[ERROR  ] configpanel:__init__:281 - [Errno 2] No such file or directory: '/Users/usr/Downloads/BallonsTranslator/ballontranslator/data/config/config.json'
Traceback (most recent call last):
  File "/Users/usr/Downloads/BallonsTranslator/ballontranslator/ui/configpanel.py", line 277, in __init__
    with open(CONFIG_PATH, 'r', encoding='utf8') as f:
FileNotFoundError: [Errno 2] No such file or directory: '/Users/usr/Downloads/BallonsTranslator/ballontranslator/data/config/config.json'
[WARNING] configpanel:__init__:282 - Failed to load config file, using default config
[INFO   ] dl_manager:on_finish_setdetector:634 - Text detector set to ctd
[INFO   ] dl_manager:on_finish_settranslator:655 - Translator set to google
[INFO   ] dl_manager:on_finish_setocr:640 - OCR set to mit32px
[INFO   ] dl_manager:on_finish_setinpainter:647 - Inpainter set to lama_mpe

可以启动了,但有提示error,这个有影响吗?

没有,这个应该搞成warning的

ghost commented 1 year ago

可以运行,我在试着打包成独立的macOS app,方便使用,不知道能不能成,如果能成,我把spec内容贴上来

ghost commented 1 year ago

翻译失败,是谷歌翻译失效了吗

Traceback (most recent call last):
  File "/Users/usr/Downloads/BallonsTranslator/ballontranslator/ui/dl_manager.py", line 187, in _translate_page
    self.translator.translate_textblk_lst(page)
  File "/Users/usr/Downloads/BallonsTranslator/ballontranslator/dl/translators/__init__.py", line 153, in translate_textblk_lst
    translations = self.translate(text_list)
  File "/Users/usr/Downloads/BallonsTranslator/ballontranslator/dl/translators/__init__.py", line 126, in translate
    text_trans = self._translate(text_source)
  File "/Users/usr/Downloads/BallonsTranslator/ballontranslator/dl/translators/__init__.py", line 213, in _translate
    translations = self.googletrans.translate(text)
  File "/Users/usr/Downloads/BallonsTranslator/ballontranslator/dl/translators/google_trans.py", line 193, in translate
    raise RequestError()
dl.translators.exceptions.RequestError: Request exception can happen due to an api connection error. Please check your connection and try again

另外打包用sudo pyinstaller --add-data "data:." -p ./dl -p ./scripts -p ./tests -p ./ui -p utils -F -w main.py 打出来1.43GB的app,但双击闪退,也没有跳出来报错信息

dmMaze commented 1 year ago

翻译失败,是谷歌翻译失效了吗

Traceback (most recent call last):
  File "/Users/usr/Downloads/BallonsTranslator/ballontranslator/ui/dl_manager.py", line 187, in _translate_page
    self.translator.translate_textblk_lst(page)
  File "/Users/usr/Downloads/BallonsTranslator/ballontranslator/dl/translators/__init__.py", line 153, in translate_textblk_lst
    translations = self.translate(text_list)
  File "/Users/usr/Downloads/BallonsTranslator/ballontranslator/dl/translators/__init__.py", line 126, in translate
    text_trans = self._translate(text_source)
  File "/Users/usr/Downloads/BallonsTranslator/ballontranslator/dl/translators/__init__.py", line 213, in _translate
    translations = self.googletrans.translate(text)
  File "/Users/usr/Downloads/BallonsTranslator/ballontranslator/dl/translators/google_trans.py", line 193, in translate
    raise RequestError()
dl.translators.exceptions.RequestError: Request exception can happen due to an api connection error. Please check your connection and try again

另外打包用sudo pyinstaller --add-data "data:." -p ./dl -p ./scripts -p ./tests -p ./ui -p utils -F -w main.py 打出来1.43GB的app,但双击闪退,也没有跳出来报错信息

设置页面把谷歌的url换掉,启用全局代理,那个.cn被谷歌扬了 我win是nuitka 打包的,不是很熟mac怎么用pyinstaller,一般问题是缺包直接把py装的拷过去就行了

另外#59是不是缺了PyQt5替换成PyQt6的提交...

ghost commented 1 year ago

换翻译器就好了,ui界面和嵌字效果比以前好不少,以前ui字和图标特别大

ghost commented 1 year ago

看了下nuitka仓库介绍,和pyinstaller使用方法差不多,我回去再试试,打成app比较方便,主要是配置python环境比较麻烦,换电脑就得重来一次

ghost commented 1 year ago

看了下nuitka仓库介绍,和pyinstaller使用方法差不多,我回去再试试

可以发一下nuitka打包windows应用的命令参考下吗

dmMaze commented 1 year ago

看了下nuitka仓库介绍,和pyinstaller使用方法差不多,我回去再试试

可以发一下nuitka打包windows应用的命令参考下吗

见scripts/build_win.bat 这条打包指令会跳过三方库的编译(不然打包时间会很长),完了你还得手动把三方库拷过去... 以后更新再打包就只更新可执行文件和其它图标模型资源(需要的话)

ghost commented 1 year ago

nuitka 在mac上打包比我预想还要复杂,还是选择用pyinstaller打吧 目前跳出来找不到module,网上搜了好几个办法都解决不了

❯ ./__main__
qtpy/__init__.py:267: RuntimeWarning: Selected binding "pyqt5" could not be found, using "pyqt6"
Traceback (most recent call last):
  File "ballontranslator/__main__.py", line 60, in <module>
  File "ballontranslator/__main__.py", line 30, in main
ModuleNotFoundError: No module named 'ui'
[45035] Failed to execute script '__main__' due to unhandled exception!
ghost commented 1 year ago

该方法实际运行可以启动、可以翻译、可以正常使用,但特殊情况下(目前原因仍不明)会在翻译环节闪退

# 安装hombrew

# 安装pyenv
brew install pyenv

# 安装Python3.9
env PYTHON_CONFIGURE_OPTS="--enable-shared" pyenv install 3.9.13

# Python全局环境改成3.9.13
pyenv global 3.9.13

# 创建Python3.9.13虚拟环境
# ballonstranslator是虚拟环境名称,随便取
python3 -m venv ballonstranslator

# 启动虚拟环境
source ballonstranslator/bin/activate

# 安装pyinstaller
# 此步是大坑,如果全局安装过pyinstaller,而虚拟环境没有安装pyinstaller,也能调用pyinstaller,但拉库会从全局库拉而不是虚拟环境
pip3 install pyinstaller

# 安装本项目依赖
# 此处有坑,requirements_macOS.txt里需要添加一行'six',否则pyinstaller打包会提示找不到模块
pip3 install -r requirements_macOS.txt

# 创建spec文件
# spec文件与__main__.py在同一个文件夹内
touch __main__.spec

# 用文本编辑器,推荐CotEditor打开__main__.spec,并将下面的内容复制粘贴进去后保存

# cd到__main__.spec所在路径,用pyinstaller打包
# 需要输入管理员密码,输入时密码不会显示,输完按回车
sudo pyinstaller __main__.spec

# 生成的app在dist文件夹内,双击运行
# 此处有坑,本项目非常、非常、非常吃内存,16GB内存不一定hold住,内存溢出启动应用会闪退,我16GB的intel mac启动应用闪退,但32GB M1 Mac启动应用不闪退
# 应用没有图标,可以自己加图标,具体方法是把icon-windowed.icns.icns文件放到 BallonsTranslator-master/ballontranslator/dist/__main__.app/Contents/Resources/icon-windowed.icns 替换原文件即可

下面是main.spec内容

# -*- mode: python ; coding: utf-8 -*-

block_cipher = None

a = Analysis(
    ['__main__.py'],
    pathex=[
        './', 
        './dl', 
        './dl/inpaint', 
        './dl/ocr', 
        './dl/textdetector', 
        './dl/textdetector/ctd', 
        './dl/textdetector/yolov5', 
        './dl/translators', 
        './scripts', 
        './tests', 
        './ui', 
        './ui/framelesswindow', 
        './ui/framelesswindow/fw_qt5', 
        './ui/framelesswindow/fw_qt5/linux', 
        './ui/framelesswindow/fw_qt5/mac', 
        './ui/framelesswindow/fw_qt5/utils', 
        './ui/framelesswindow/fw_qt5/windows', 
        './ui/framelesswindow/fw_qt6', 
        './ui/framelesswindow/fw_qt6/linux', 
        './ui/framelesswindow/fw_qt6/mac', 
        './ui/framelesswindow/fw_qt6/utils', 
        './ui/framelesswindow/fw_qt6/windows', 
        './utils'],
    binaries=[],
    datas=[('data', './data')],
    hiddenimports=[],
    hookspath=[],
    hooksconfig={},
    runtime_hooks=[],
    excludes=[],
    win_no_prefer_redirects=False,
    win_private_assemblies=False,
    cipher=block_cipher,
    noarchive=False,
)
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)

exe = EXE(
    pyz,
    a.scripts,
    [],
    exclude_binaries=True,
    name='__main__',
    debug=False,
    bootloader_ignore_signals=False,
    strip=False,
    upx=True,
    console=False,
    disable_windowed_traceback=False,
    argv_emulation=False,
    target_arch=None,
    codesign_identity=None,
    entitlements_file=None,
)
coll = COLLECT(
    exe,
    a.binaries,
    a.zipfiles,
    a.datas,
    strip=False,
    upx=True,
    upx_exclude=[],
    name='__main__',
)
app = BUNDLE(
    coll,
    name='__main__.app',
    icon=None,
    bundle_identifier=None,
)

找网络素材随便组了个图标,比较丑,希望作者能提供个官方图标

截屏2022-12-07 11 24 37

启动画面和运行画面(漫画生肉是百度上随便找的,搜索“漫画生肉”)

截屏2022-12-07 11 52 40

现在仍然遇到一些问题:

运行翻译的时候,有时候(是有时候)到翻译环节会闪退,报错类型的官方解释如下

EXC_CRASH (SIGABRT) EXC_CRASH (SIGABRT) indicates the process terminated because it received the SIGABRT signal. Typically, this signal is sent because a function in the process called abort(), such as when an app encounters an uncaught Objective-C or C++ language exception. Addressing language exception crashes explains how to handle uncaught language exceptions in more detail.

If there isn’t a Last Exception Backtrace indicating a langauge exception triggered the crash, look at the crashed thread’s backtrace to determine if code in the process called abort().

When an app extension takes too much time to initialize, the operating system sends a SIGABRT to the app extension process. These crashes include an Exception Subtype field with the value LAUNCH_HANG. Because extensions don’t have a main function, any time spent initializing occurs within static constructors and load() methods present in your extension and dependent libraries. Although the exception information is different in a watchdog termination, investigate the LAUNCH_HANG with the same techniques discussed in Addressing watchdog terminations.

看意思似乎和C有关,然后我回想起打包过程中的warning信息好像是提示找不到ctype下的什么文件,pypi上也没有ctype包,请问这是个啥,要怎么处理解决这个问题?

其他

1、app本身有2.4GB(包含了checkpoint模型等大型数据文件),但打成macOS的dmg镜像后只有1.5GB(还是挺大的,这是模型文件无法再压缩了) 2、打包成macOS app的目的是可以独立运行而不需要换台电脑和换个环境就要繁琐的重新搭建环境,可以随拿随用,对于更新频度不高,或应用体积特别大,环境要求比较特殊(比如这个项目要python3.9,而目前已经到3.11了,项目不兼容3.10和3.11)的项目,打包是一个比较经济比较实用的方式 3、如果是比较小又没有GUI的项目,我一般是打包成wheel用pip安装到本地库,方便随时调用,但这个做法跟项目本身代码质量有很大关系,实际操作下来,有些项目可以直接写个setup.py就能解决问题,有些还需要稍微修改下源代码以符合setuptools的要求,坑特别多,哪怕只有1个py文件的项目,都遇到过令人无语的问题 4、折腾打包还是一件比较有趣的事情

最后还是要感谢作者这个了不起的开源项目!

dmMaze commented 1 year ago

此处有坑,本项目非常、非常、非常吃内存,16GB内存不一定hold住,内存溢出启动应用会闪退,我16GB的intel mac启动应用闪退,但32GB M1 Mac启动应用不闪退

跑模型前windows上占用内存不到400M, 跑后不到4G... macOS上跑打包的程序和源码都占那么大内存吗...

找网络素材随便组了个图标,比较丑,希望作者能提供个官方图标

本来有意试下用最近的一些diffusion来搞不过一直搁了

运行翻译的时候,有时候(是有时候)到翻译环节会闪退,报错类型的官方解释如下

这个问题是打包的有还是在mac上跑源码也有? 如果是打包程序闪退,用终端启动,闪退了可以看到报错信息然后搜那个...我没mac感觉也帮不上啥

最后感谢折腾~

ghost commented 1 year ago

此处有坑,本项目非常、非常、非常吃内存,16GB内存不一定hold住,内存溢出启动应用会闪退,我16GB的intel mac启动应用闪退,但32GB M1 Mac启动应用不闪退

跑模型前windows上占用内存不到400M, 跑后不到4G... macOS上跑打包的程序和源码都占那么大内存吗...

源码和app都占这么大内存,动辄20g内存,可能跟mac内存机制有关

找网络素材随便组了个图标,比较丑,希望作者能提供个官方图标

本来有意试下用最近的一些diffusion来搞不过一直搁了

sd ai画图入门挺难的

运行翻译的时候,有时候(是有时候)到翻译环节会闪退,报错类型的官方解释如下

这个问题是打包的有还是在mac上跑源码也有? 如果是打包程序闪退,用终端启动,闪退了可以看到报错信息然后搜那个...我没mac感觉也帮不上啥

最后感谢折腾~

我明天试试,ctypes是cpython的一部分,我明天安装cpython看看