TransparentLC / realesrgan-gui

实用、美观的 Real-ESRGAN 图形界面,同时支持 Windows、Ubuntu 和 macOS 平台。现在也支持 Real-CUGAN 了!(Cross-platform GUI for image upscaler Real-ESRGAN with additional features. Now with Real-CUGAN support!)
http://akarin.dev/realesrgan-gui/
GNU Affero General Public License v3.0
808 stars 45 forks source link

release下载的macos在m2 mac上双击图标闪退【已解决】 #39

Closed hyrulelinks closed 1 year ago

hyrulelinks commented 1 year ago

如题,已经xattr -cr,但双击图标闪退,无法打开应用,按照readme本地构建,可以构建成功,但一样闪退

已经装了rosseta2,release里面虽然是x64版本的,但理论上应该可以兼容在m2 mac上跑才对

TransparentLC commented 1 year ago

⚠️ 由于我没有运行 macOS 的设备,因此可能无法处理和 macOS 相关的使用问题。

不构建而是直接从源码运行的话也不能正常使用吗?

之前提供 macOS 下的使用建议的那位注销账号了,我也没什么头绪。

hyrulelinks commented 1 year ago

更新下,release中3月14日前的都可以正常打开,就2天前刚发布的无法打开

hyrulelinks commented 1 year ago
截屏2023-08-31 23 42 54

左边是3月14日版本,右边是8月29日版本,新版多了些东西,反而无法正常运行了

TransparentLC commented 1 year ago

在那之后 macOS 的打包我一直没动过来着……

3.14 的那个 release 对应的是 aa5479e 这个 commit,如果你有条件从源码运行的话可以在这个 commit 和最近的 commit 之间折半查找一下(不到 16 个),应该就能定位到是哪个 commit 可能有问题?

hyrulelinks commented 1 year ago

在那之后 macOS 的打包我一直没动过来着……

3.14 的那个 release 对应的是 aa5479e 这个 commit,如果你有条件从源码运行的话可以在这个 commit 和最近的 commit 之间折半查找一下(不到 16 个),应该就能定位到是哪个 commit 可能有问题?

直接运行源码发现可能问题所在:用python3.10虚拟环境,自带tk版本8.5,运行报错package "Tk": have 8.5.9, need 8.6,改用python11虚拟环境,自带tk版本是8.6,运行成功。

建议readme里面写一下python版本

用pyinstaller打包成功,但双击闪退,也不知道是什么错误,怎么看错误信息呢

hyrulelinks commented 1 year ago

进入打包的appbundle,直接运行主程序,看到报错信息如下:

❯ ./realesrgan-gui
Traceback (most recent call last):
  File "PyInstaller/hooks/rthooks/pyi_rth_multiprocessing.py", line 109, in <module>
  File "PyInstaller/hooks/rthooks/pyi_rth_multiprocessing.py", line 97, in _pyi_rthook
  File "PyInstaller/loader/pyimod02_importers.py", line 385, in exec_module
  File "multiprocessing/popen_forkserver.py", line 7, in <module>
  File "PyInstaller/loader/pyimod02_importers.py", line 385, in exec_module
  File "multiprocessing/forkserver.py", line 11, in <module>
  File "PyInstaller/loader/pyimod02_importers.py", line 385, in exec_module
  File "multiprocessing/connection.py", line 21, in <module>
ModuleNotFoundError: No module named '_multiprocessing'
[67379] Failed to execute script 'pyi_rth_multiprocessing' due to unhandled exception: No module named '_multiprocessing'
[67379] Traceback:
Traceback (most recent call last):
  File "PyInstaller/hooks/rthooks/pyi_rth_multiprocessing.py", line 109, in <module>
  File "PyInstaller/hooks/rthooks/pyi_rth_multiprocessing.py", line 97, in _pyi_rthook
  File "PyInstaller/loader/pyimod02_importers.py", line 385, in exec_module
  File "multiprocessing/popen_forkserver.py", line 7, in <module>
  File "PyInstaller/loader/pyimod02_importers.py", line 385, in exec_module
  File "multiprocessing/forkserver.py", line 11, in <module>
  File "PyInstaller/loader/pyimod02_importers.py", line 385, in exec_module
  File "multiprocessing/connection.py", line 21, in <module>
ModuleNotFoundError: No module named '_multiprocessing'

这个缺失的module是什么?

TransparentLC commented 1 year ago

Actions 运行的时候用的就是 Python 3.11,应该不会碰到 tk 的版本问题。

为了减少程序体积,打包的时候我会试着把 Python 自带的但是程序里没有调用的模块阉割掉,看样子在 macOS 打包的时候这个 _multiprocessing 不应该去掉(

把 spec 文件的 excludes 里面的 '_multiprocessing' 去掉再打包试试看?如果还缺了别的模块,解决办法也是类似的。

(Linux 下能不能运行我也很久没测试过了,明天起来有空试一下)

hyrulelinks commented 1 year ago

把 spec 文件的 excludes 里面的 '_multiprocessing' 去掉再打包后,进入appbundle运行主程序的信息如下:

❯ ./realesrgan-gui
2023-09-01 00:20:26.629 realesrgan-gui[71375:607187] WARNING: Secure coding is not enabled for restorable state! Enable secure coding by implementing NSApplicationDelegate.applicationSupportsSecureRestorableState: and returning YES.
Traceback (most recent call last):
  File "main.py", line 477, in <module>
  File "<frozen importlib._bootstrap>", line 1176, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1147, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 690, in _load_unlocked
  File "PyInstaller/loader/pyimod02_importers.py", line 385, in exec_module
  File "darkdetect/__init__.py", line 27, in <module>
  File "darkdetect/__init__.py", line 14, in macos_supported_version
ValueError: invalid literal for int() with base 10: ''

运行打包好的mac app可以正常打开了,问题确实出在excludes里面的 '_multiprocessing'

TransparentLC commented 1 year ago

这个输出是因为上游的 darkdetect 库的问题,import 的语句已经被包在 try: ... except: ... 里面了。

等我确认 Linux 下有没有类似问题之后就重新发 release。

更新:Linux 下也需要 _multiprocessing,看来只有 Windows 下可以去掉。

hyrulelinks commented 1 year ago

忘了提了,spec要改成下面这样,不然pyinstaller打包会报错,原因是models里面的bin文件的mach-o无法解析

    binaries=[
    ],
    datas=[
        ('realesrgan-ncnn-vulkan', '.'),
        ('models', 'models'),

或者

    binaries=[
        ('realesrgan-ncnn-vulkan', '.'),
    ],
    datas=[
        ('models', 'models'),

上面这两种写法都可以打包成功,问题出在models不能放在binaries里面

hyrulelinks commented 1 year ago

下面是我改过的完整的realesrgan-gui-macOS-arm64.spec,版本号我把最后一个0改成commit版本了,方便区分commit版本

import os
import sys
from PyInstaller.utils.hooks import collect_data_files

a = Analysis(
    ['main.py'],
    binaries=[
        ('realesrgan-ncnn-vulkan', '.'),
    ],
    datas=[
        ('models', 'models'),
        ('theme', 'theme'),
        ('i18n.ini', '.'),
        ('icon.icns', '.'),
        ('icon-128px.png', '.'),
        # macOS下通过app实现通知,打包时需要附带
        *(collect_data_files('notifypy') if sys.platform == 'darwin' else []),
    ],
    hiddenimports=[
        'PIL._tkinter_finder',
    ],
    hookspath=[
        'pyi-hooks',
    ],
    excludes=[
        '_asyncio',
        '_bz2',
        '_decimal',
        '_hashlib',
        '_lzma',
        '_queue',
        '_ssl',
        'pyexpat',
        'unicodedata',
    ],
)

# Windows 10+已经自带UCRT了,打包时不需要附带
a.binaries = [
    x
    for x in a.binaries
    if not any(x[0].startswith(y) for y in {
        'api-ms-win-',
        'ucrtbase.dll',
    })
]

# tcl/tk相关的没有实际使用的大量小文件,在不使用onefile的情况下打包测试,即使不附带这些文件也后不影响运行
a.datas = [
    x
    for x in a.datas
    if not any(x[0].startswith(y) for y in {
        os.path.join('tcl', 'encoding'),
        os.path.join('tcl', 'http'),
        os.path.join('tcl', 'msgs'),
        os.path.join('tcl', 'opt'),
        os.path.join('tcl', 'tzdata'),
        os.path.join('tcl8'),
        os.path.join('tk', 'images'),
        os.path.join('tk', 'msgs'),
    })
]

print('Binaries:')
for i in a.binaries:
    print(i)

print('Datas:')
for i in a.datas:
    print(i)

pyz = PYZ(a.pure, a.zipped_data)

if os.environ.get('REGUI_ONEFILE'):
    exe = EXE(
        pyz,
        a.scripts,
        a.binaries,
        a.zipfiles,
        a.datas,
        [],
        name='realesrgan-gui',
        debug=False,
        bootloader_ignore_signals=False,
        strip=False,
        upx=True,
        console=False,
        disable_windowed_traceback=False,
        argv_emulation=False,
        icon='icon.icns',
    )
else:
    exe = EXE(
        pyz,
        a.scripts,
        [],
        exclude_binaries=True,
        name='realesrgan-gui',
        debug=False,
        bootloader_ignore_signals=False,
        strip=False,
        upx=True,
        console=False,
        disable_windowed_traceback=False,
        argv_emulation=False,
        icon='icon.icns',
    )
    coll = COLLECT(
        exe,
        a.binaries,
        a.zipfiles,
        a.datas,
        name='realesrgan-gui',
        strip=False,
        upx=True,
    )
    app = BUNDLE(
    coll,
    name='Real-ESRGAN GUI.app',
    icon='icon.icns',
    bundle_identifier=None,
    info_plist={
            'CFBundleDisplayName': 'Real-ESRGAN GUI',
            'CFBundleName': 'Real-ESRGAN GUI',
            'CFBundlePackageType': 'APPL',
            'CFBundleSignature': 'RLES',
            'CFBundleShortVersionString': '0.2.5.66ddfb3',
            'CFBundleVersion': '0.2.5.66ddfb3',
            'CFBundleExecutable': 'realesrgan-gui',
            'CFBundleIconFile': 'icon.icns',
            'CFBundleIdentifier': 'dev.transparentlc.regui',
            'CFBundleInfoDictionaryVersion': '6.0',
            'LSApplicationCategoryType': 'public.app-category.graphics-design',
            'LSEnvironment': {'LANG': 'zh_CN.UTF-8'},
            }
    )
hyrulelinks commented 1 year ago

我本地源码打包过程如下

下载源码和Python虚拟环境

git clone https://github.com/TransparentLC/realesrgan-gui.git cd realesrgan-gui pyenv global 3.11.5 python3 -m venv venv4build source venv4build/bin/activate pip3 install -r requirements.txt pip3 install pyinstaller

下载realesrgan-ncnn-vulkan

curl -L "https://github.com/xinntao/Real-ESRGAN/releases/download/v0.2.5.0/realesrgan-ncnn-vulkan-20220424-macos.zip" -o realesrgan-ncnn-vulkan-20220424-macos.zip unzip -o realesrgan-ncnn-vulkan-20220424-macos.zip rm -f realesrgan-ncnn-vulkan-20220424-macos.zip input.jpg input2.jpg onepiece_demo.mp4 lipo realesrgan-ncnn-vulkan -extract arm64 -output realesrgan-ncnn-vulkan-arm64 rm -f realesrgan-ncnn-vulkan mv realesrgan-ncnn-vulkan-arm64 realesrgan-ncnn-vulkan chmod u+x realesrgan-ncnn-vulkan

按照上面说的修改spec文件后打包app

sudo pyinstaller realesrgan-gui-macOS-arm64.spec

TransparentLC commented 1 year ago

你都把改好的 spec 端上来了,那提个 PR 吧 ( ゚∀。) build.yml 或者 README.md 的 macOS 相关内容如果有需要补充的也可以改。

commit hash 可以不用写死。spec 文件其实也是 Python 代码,可以试试改成用 subprocess 调用 git rev-parse --short HEAD 来获取当前的 commit hash。

TransparentLC commented 1 year ago

已经 merge 了,先试试 actions 里面最新的打包用起来有没有问题?

hyrulelinks commented 1 year ago

已经 merge 了,先试试 actions 里面最新的打包用起来有没有问题?

action里面下载的macOS app bundle无法打开

hyrulelinks commented 1 year ago

但是完全按照readme里面一键打包 arm64 单架构的 Real-ESRGAN GUI.app步骤操作已经能够打包成能正常打开的arm64单架构app了

TransparentLC commented 1 year ago

有一点不知道是不是和这个问题有关,actions 的 macOS 运行环境只有 x64 没有 arm,不过如果真的是因为这个的话我也没办法解决了……

hyrulelinks commented 1 year ago

github macos runner 很久前就说要上arm64的,但一直没见上,不知道是不是我没找到对的runner标识,如果是x64,理论上apple芯片也是兼容的,证据就是3月14日之前的release都是x64的,可以在我的M2 Mac上正常运行。我还有台intel芯片的老mac,有空我拿出来试下看看问题出在哪。

另外有个PR的问题,应该是我这边哪里弄错了,就是作者改的multiprocessing按操作系统判断是否剔除模块的代码,好像因为我的Readme那个PR被删除了,请再改回来,我再直接sync到我的仓库,抱歉,谢谢!

截屏2023-09-01 17 40 11
TransparentLC commented 1 year ago

我才发现 Actions 里面还是三个系统都使用 realesrgan-gui.spec,改成使用那个 Build-macOS-arm64.sh 好了,如果可以的话你可以 fork 之后直接动手改 build.yml 然后看打包出来的东西能不能运行。

现在 realesrgan-gui.spec 是只有 Windows 才会剔除 multiprocessing,realesrgan-gui-macOS-arm64.spec 没有剔除,这个应该没有问题。

github macos runner 很久前就说要上arm64的,但一直没见上

鸽了,鸽到 Q4 2023 了。

GitHub Actions: Apple Silicon (M1) powered macOS runners (Public Beta) · Issue #528 · github/roadmap

hyrulelinks commented 1 year ago

action workflow如下:

name: buildmac

on:
  push:
    branches:
      - master

jobs:
  release:
    runs-on: macos-latest

    steps:
      - name: check out git repository
        uses: actions/checkout@v3

      - name: Setup Python
        uses: actions/setup-python@v4
        with:
          python-version: 3.11
          check-latest: true
          cache: pip
          cache-dependency-path: requirements.txt

      - name: Install pip dependencies
        run: |
          pip install -U -r requirements.txt
          pip install pyinstaller

      - name: Setup UPX
        run: brew install upx

      - name: Run shell script to build
        run: sh Build-macOS-arm64.sh

      - name: upload artifacts
        uses: actions/upload-artifact@v3
        with:
          name: app-x64-macos
          path: dist/*.app

这是用github action打包的intel芯片 macOS app

截屏2023-09-01 20 46 19

从action下载后无法启动,报错和作者的release一样,提示无法启动应用,进入app bundle文件夹后,发现realesrgan-gui和realesrgan-ncnn-vulkan都没有权限,是应用无法启动的原因,解决办法如下,cd到app所在路径,在终端中运行如下命令:

chmod u+x ./Real-ESRGAN GUI.app/Contents/MacOS/realesrgan-gui
chmod u+x ./Real-ESRGAN GUI.app/Contents/MacOS/realesrgan-ncnn-vulkan
xattr -cr ./Real-ESRGAN\ GUI.app

然后双击就能正常启动运行了

TransparentLC commented 1 year ago
if [ $RUNNER_OS == "macOS" ]; then
  chmod +x Build-macOS-arm64.sh
  sh Build-macOS-arm64.sh
  chmod u+x "dist/Real-ESRGAN GUI.app/Contents/MacOS/realesrgan-gui"
  chmod u+x "dist/Real-ESRGAN GUI.app/Contents/MacOS/realesrgan-ncnn-vulkan"
  xattr -cr "dist/Real-ESRGAN GUI.app"
else
  pyinstaller --clean --log-level WARN realesrgan-gui.spec
fi

按照这个修改了 build.yml 里打包相关的部分。

hyrulelinks commented 1 year ago
chmod u+x "dist/Real-ESRGAN GUI.app/Contents/MacOS/realesrgan-gui"
  chmod u+x "dist/Real-ESRGAN GUI.app/Contents/MacOS/realesrgan-ncnn-vulkan"
  xattr -cr "dist/Real-ESRGAN GUI.app"

试了下action打包出来的还是无法启动,应该是只能在本地操作上面的权限,或者有其他方式在action中赋予权限

hyrulelinks commented 1 year ago

8月28日release里面的macos app,realesrgan-gui和realesrgan-ncnn-vulkan都有权限,但无法启动,原因是之前一样的multiprocessing模块缺失,所以我猜测只要把模块加上应该就能运行了; 然后action里用脚本构建的版本,realesrgan-gui和realesrgan-ncnn-vulkan都没有权限,不知道什么原因造成的,而且无法用action里面chmod赋权来解决

TransparentLC commented 1 year ago

那应该没办法了,只能把这几个命令写在README里自己动手执行了(

hyrulelinks commented 1 year ago

那应该没办法了,只能把这几个命令写在README里自己动手执行了(

作者用回原来的workflow,用回原来的spec文件,把multiprocessing模块从排除清单删掉(包括win和mac,不做条件判断),是不是其实就可以了?因为原来的workflow好像没有可执行程序没有权限的问题

TransparentLC commented 1 year ago

我没办法说可不可以啊(笑

同样是 Actions 里面 chmod 然后打包进 tar,Linux 的版本是解压后直接有 +x 权限的,我也不知道 macOS 为什么不行或者说为什么以前可以现在不行……

因为我没有 macOS 设备也完全不了解相关机制,所以现在这种需要输命令之类的操作但是至少能跑起来已经是我能做到的上限了(

hyrulelinks commented 1 year ago

我没办法说可不可以啊(笑

同样是 Actions 里面 chmod 然后打包进 tar,Linux 的版本是解压后直接有 +x 权限的,我也不知道 macOS 为什么不行或者说为什么以前可以现在不行……

因为我没有 macOS 设备也完全不了解相关机制,所以现在这种需要输命令之类的操作但是至少能跑起来已经是我能做到的上限了(

9月3日macOS intel芯片版本已经解决无法启动的问题了,作者👍🏻

hyrulelinks commented 1 year ago

@TransparentLC 可能是pyinstaller新版本做了什么修改,重新打包项目后,除了主程序realesrgan-guiMacOS文件夹外,其余原先在MacOS文件夹的文件全部在Frameworks文件夹了,然后打包好的应用双击运行会提示找不到realesrgan-ncnn-vulkan,可否修复下这个issue,谢谢作者!

hyrulelinks commented 1 year ago

下面这是原先的appbundle结构

Real-ESRGAN GUI.app/Contents
├── Frameworks
├── Info.plist
├── MacOS
│   ├── AppKit
│   │   ├── _AppKit.cpython-311-darwin.so
│   │   └── _inlines.cpython-311-darwin.so
│   ├── CoreFoundation
│   │   ├── _CoreFoundation.cpython-311-darwin.so
│   │   └── _inlines.cpython-311-darwin.so
│   ├── Foundation
│   │   ├── _Foundation.cpython-311-darwin.so
│   │   └── _inlines.cpython-311-darwin.so
│   ├── PIL
│   │   ├── _imaging.cpython-311-darwin.so
│   │   ├── _imagingcms.cpython-311-darwin.so
│   │   ├── _imagingtk.cpython-311-darwin.so
│   │   └── _webp.cpython-311-darwin.so
│   ├── base_library.zip -> ../Resources/base_library.zip
│   ├── i18n.ini -> ../Resources/i18n.ini
│   ├── icon-128px.png -> ../Resources/icon-128px.png
│   ├── icon.icns -> ../Resources/icon.icns
│   ├── lib-dynload
│   │   ├── _bisect.cpython-311-darwin.so
│   │   ├── _blake2.cpython-311-darwin.so
│   │   ├── _codecs_cn.cpython-311-darwin.so
│   │   ├── _codecs_hk.cpython-311-darwin.so
│   │   ├── _codecs_iso2022.cpython-311-darwin.so
│   │   ├── _codecs_jp.cpython-311-darwin.so
│   │   ├── _codecs_kr.cpython-311-darwin.so
│   │   ├── _codecs_tw.cpython-311-darwin.so
│   │   ├── _contextvars.cpython-311-darwin.so
│   │   ├── _csv.cpython-311-darwin.so
│   │   ├── _ctypes.cpython-311-darwin.so
│   │   ├── _datetime.cpython-311-darwin.so
│   │   ├── _elementtree.cpython-311-darwin.so
│   │   ├── _heapq.cpython-311-darwin.so
│   │   ├── _json.cpython-311-darwin.so
│   │   ├── _md5.cpython-311-darwin.so
│   │   ├── _multibytecodec.cpython-311-darwin.so
│   │   ├── _multiprocessing.cpython-311-darwin.so
│   │   ├── _opcode.cpython-311-darwin.so
│   │   ├── _pickle.cpython-311-darwin.so
│   │   ├── _posixshmem.cpython-311-darwin.so
│   │   ├── _posixsubprocess.cpython-311-darwin.so
│   │   ├── _random.cpython-311-darwin.so
│   │   ├── _scproxy.cpython-311-darwin.so
│   │   ├── _sha1.cpython-311-darwin.so
│   │   ├── _sha256.cpython-311-darwin.so
│   │   ├── _sha3.cpython-311-darwin.so
│   │   ├── _sha512.cpython-311-darwin.so
│   │   ├── _socket.cpython-311-darwin.so
│   │   ├── _statistics.cpython-311-darwin.so
│   │   ├── _struct.cpython-311-darwin.so
│   │   ├── _tkinter.cpython-311-darwin.so
│   │   ├── _typing.cpython-311-darwin.so
│   │   ├── _uuid.cpython-311-darwin.so
│   │   ├── array.cpython-311-darwin.so
│   │   ├── binascii.cpython-311-darwin.so
│   │   ├── fcntl.cpython-311-darwin.so
│   │   ├── grp.cpython-311-darwin.so
│   │   ├── math.cpython-311-darwin.so
│   │   ├── mmap.cpython-311-darwin.so
│   │   ├── readline.cpython-311-darwin.so
│   │   ├── resource.cpython-311-darwin.so
│   │   ├── select.cpython-311-darwin.so
│   │   ├── termios.cpython-311-darwin.so
│   │   └── zlib.cpython-311-darwin.so
│   ├── libXau.6.0.0.dylib
│   ├── libb2.1.dylib
│   ├── libintl.8.dylib
│   ├── liblcms2.2.dylib
│   ├── liblzma.5.dylib
│   ├── libopenjp2.2.5.0.dylib
│   ├── libpython3.11.dylib
│   ├── libreadline.8.dylib
│   ├── libsharpyuv.0.dylib
│   ├── libtcl8.6.dylib
│   ├── libtiff.6.dylib
│   ├── libtk8.6.dylib
│   ├── libwebp.7.dylib
│   ├── libwebpdemux.2.dylib
│   ├── libwebpmux.3.dylib
│   ├── libxcb.1.1.0.dylib
│   ├── libz.1.2.13.dylib
│   ├── models -> ../Resources/models
│   ├── notifypy -> ../Resources/notifypy
│   ├── objc
│   │   ├── _machsignals.cpython-311-darwin.so
│   │   └── _objc.cpython-311-darwin.so
│   ├── realesrgan-gui
│   ├── realesrgan-ncnn-vulkan
│   ├── tcl -> ../Resources/tcl
│   ├── theme -> ../Resources/theme
│   ├── tk -> ../Resources/tk
│   └── tkinterdnd2 -> ../Resources/tkinterdnd2
├── Resources
│   ├── base_library.zip
│   ├── i18n.ini
│   ├── icon-128px.png
│   ├── icon.icns
│   ├── models
│   │   ├── 4x-AnimeSharp.bin
│   │   ├── 4x-AnimeSharp.param
│   │   ├── realesr-animevideov3-x2.bin
│   │   ├── realesr-animevideov3-x2.param
│   │   ├── realesr-animevideov3-x3.bin
│   │   ├── realesr-animevideov3-x3.param
│   │   ├── realesr-animevideov3-x4.bin
│   │   ├── realesr-animevideov3-x4.param
│   │   ├── realesrgan-x4plus-anime.bin
│   │   ├── realesrgan-x4plus-anime.param
│   │   ├── realesrgan-x4plus.bin
│   │   ├── realesrgan-x4plus.param
│   │   ├── realsr-x4.bin
│   │   └── realsr-x4.param
│   ├── notifypy
│   │   ├── example_notification_sound.wav
│   │   ├── os_notifiers
│   │   │   └── binaries
│   │   │       └── Notificator.app
│   │   │           └── Contents
│   │   │               ├── Info.plist
│   │   │               ├── MacOS
│   │   │               │   └── applet
│   │   │               ├── PkgInfo
│   │   │               └── Resources
│   │   │                   ├── Scripts
│   │   │                   │   ├── main.scpt
│   │   │                   │   └── notificator
│   │   │                   ├── applet.icns
│   │   │                   └── applet.rsrc
│   │   └── py-logo.png
│   ├── tcl
│   │   ├── auto.tcl
│   │   ├── clock.tcl
│   │   ├── history.tcl
│   │   ├── init.tcl
│   │   ├── package.tcl
│   │   ├── parray.tcl
│   │   ├── safe.tcl
│   │   ├── tclAppInit.c
│   │   ├── tclIndex
│   │   ├── tm.tcl
│   │   └── word.tcl
│   ├── theme
│   │   ├── dark.png
│   │   ├── light.png
│   │   └── sun-valley.tcl
│   ├── tk
│   │   ├── bgerror.tcl
│   │   ├── button.tcl
│   │   ├── choosedir.tcl
│   │   ├── clrpick.tcl
│   │   ├── comdlg.tcl
│   │   ├── console.tcl
│   │   ├── dialog.tcl
│   │   ├── entry.tcl
│   │   ├── focus.tcl
│   │   ├── fontchooser.tcl
│   │   ├── iconlist.tcl
│   │   ├── icons.tcl
│   │   ├── listbox.tcl
│   │   ├── megawidget.tcl
│   │   ├── menu.tcl
│   │   ├── mkpsenc.tcl
│   │   ├── msgbox.tcl
│   │   ├── obsolete.tcl
│   │   ├── optMenu.tcl
│   │   ├── palette.tcl
│   │   ├── panedwindow.tcl
│   │   ├── pkgIndex.tcl
│   │   ├── safetk.tcl
│   │   ├── scale.tcl
│   │   ├── scrlbar.tcl
│   │   ├── spinbox.tcl
│   │   ├── tclIndex
│   │   ├── tearoff.tcl
│   │   ├── text.tcl
│   │   ├── tk.tcl
│   │   ├── tkAppInit.c
│   │   ├── tkfbox.tcl
│   │   ├── ttk
│   │   │   ├── altTheme.tcl
│   │   │   ├── aquaTheme.tcl
│   │   │   ├── button.tcl
│   │   │   ├── clamTheme.tcl
│   │   │   ├── classicTheme.tcl
│   │   │   ├── combobox.tcl
│   │   │   ├── cursors.tcl
│   │   │   ├── defaults.tcl
│   │   │   ├── entry.tcl
│   │   │   ├── fonts.tcl
│   │   │   ├── menubutton.tcl
│   │   │   ├── notebook.tcl
│   │   │   ├── panedwindow.tcl
│   │   │   ├── progress.tcl
│   │   │   ├── scale.tcl
│   │   │   ├── scrollbar.tcl
│   │   │   ├── sizegrip.tcl
│   │   │   ├── spinbox.tcl
│   │   │   ├── treeview.tcl
│   │   │   ├── ttk.tcl
│   │   │   ├── utils.tcl
│   │   │   ├── vistaTheme.tcl
│   │   │   ├── winTheme.tcl
│   │   │   └── xpTheme.tcl
│   │   ├── unsupported.tcl
│   │   └── xmfbox.tcl
│   └── tkinterdnd2
│       └── tkdnd
│           └── osx-arm64
│               ├── libtkdnd2.9.3.dylib
│               ├── pkgIndex.tcl
│               ├── tkdnd.tcl
│               ├── tkdnd_compat.tcl
│               ├── tkdnd_generic.tcl
│               ├── tkdnd_macosx.tcl
│               └── tkdnd_utils.tcl
└── _CodeSignature
    └── CodeResources

33 directories, 188 files

下面这是新的结构

Real-ESRGAN GUI.app/Contents
├── Frameworks
│   ├── AppKit
│   │   ├── _AppKit.cpython-311-darwin.so
│   │   └── _inlines.cpython-311-darwin.so
│   ├── CoreFoundation
│   │   ├── _CoreFoundation.cpython-311-darwin.so
│   │   └── _inlines.cpython-311-darwin.so
│   ├── Foundation
│   │   ├── _Foundation.cpython-311-darwin.so
│   │   └── _inlines.cpython-311-darwin.so
│   ├── PIL
│   │   ├── __dot__dylibs
│   │   │   ├── libXau.6.0.0.dylib
│   │   │   ├── liblcms2.2.dylib
│   │   │   ├── liblzma.5.dylib
│   │   │   ├── libopenjp2.2.5.0.dylib
│   │   │   ├── libsharpyuv.0.dylib
│   │   │   ├── libtiff.6.dylib
│   │   │   ├── libwebp.7.dylib
│   │   │   ├── libwebpdemux.2.dylib
│   │   │   ├── libwebpmux.3.dylib
│   │   │   ├── libxcb.1.1.0.dylib
│   │   │   └── libz.1.2.13.dylib
│   │   ├── _imaging.cpython-311-darwin.so
│   │   ├── _imagingcms.cpython-311-darwin.so
│   │   ├── _imagingtk.cpython-311-darwin.so
│   │   └── _webp.cpython-311-darwin.so
│   ├── base_library.zip -> ../Resources/base_library.zip
│   ├── i18n.ini -> ../Resources/i18n.ini
│   ├── icon-128px.png -> ../Resources/icon-128px.png
│   ├── icon.icns -> ../Resources/icon.icns
│   ├── lib-dynload
│   │   ├── _bisect.cpython-311-darwin.so
│   │   ├── _blake2.cpython-311-darwin.so
│   │   ├── _codecs_cn.cpython-311-darwin.so
│   │   ├── _codecs_hk.cpython-311-darwin.so
│   │   ├── _codecs_iso2022.cpython-311-darwin.so
│   │   ├── _codecs_jp.cpython-311-darwin.so
│   │   ├── _codecs_kr.cpython-311-darwin.so
│   │   ├── _codecs_tw.cpython-311-darwin.so
│   │   ├── _contextvars.cpython-311-darwin.so
│   │   ├── _csv.cpython-311-darwin.so
│   │   ├── _ctypes.cpython-311-darwin.so
│   │   ├── _datetime.cpython-311-darwin.so
│   │   ├── _elementtree.cpython-311-darwin.so
│   │   ├── _heapq.cpython-311-darwin.so
│   │   ├── _json.cpython-311-darwin.so
│   │   ├── _md5.cpython-311-darwin.so
│   │   ├── _multibytecodec.cpython-311-darwin.so
│   │   ├── _multiprocessing.cpython-311-darwin.so
│   │   ├── _opcode.cpython-311-darwin.so
│   │   ├── _pickle.cpython-311-darwin.so
│   │   ├── _posixshmem.cpython-311-darwin.so
│   │   ├── _posixsubprocess.cpython-311-darwin.so
│   │   ├── _random.cpython-311-darwin.so
│   │   ├── _scproxy.cpython-311-darwin.so
│   │   ├── _sha1.cpython-311-darwin.so
│   │   ├── _sha256.cpython-311-darwin.so
│   │   ├── _sha3.cpython-311-darwin.so
│   │   ├── _sha512.cpython-311-darwin.so
│   │   ├── _socket.cpython-311-darwin.so
│   │   ├── _statistics.cpython-311-darwin.so
│   │   ├── _struct.cpython-311-darwin.so
│   │   ├── _tkinter.cpython-311-darwin.so
│   │   ├── _typing.cpython-311-darwin.so
│   │   ├── _uuid.cpython-311-darwin.so
│   │   ├── array.cpython-311-darwin.so
│   │   ├── binascii.cpython-311-darwin.so
│   │   ├── fcntl.cpython-311-darwin.so
│   │   ├── grp.cpython-311-darwin.so
│   │   ├── math.cpython-311-darwin.so
│   │   ├── mmap.cpython-311-darwin.so
│   │   ├── pyexpat.cpython-311-darwin.so
│   │   ├── readline.cpython-311-darwin.so
│   │   ├── resource.cpython-311-darwin.so
│   │   ├── select.cpython-311-darwin.so
│   │   ├── termios.cpython-311-darwin.so
│   │   └── zlib.cpython-311-darwin.so
│   ├── libXau.6.0.0.dylib -> PIL/.dylibs/libXau.6.0.0.dylib
│   ├── libb2.1.dylib
│   ├── libintl.8.dylib
│   ├── liblcms2.2.dylib -> PIL/.dylibs/liblcms2.2.dylib
│   ├── liblzma.5.dylib -> PIL/.dylibs/liblzma.5.dylib
│   ├── libopenjp2.2.5.0.dylib -> PIL/.dylibs/libopenjp2.2.5.0.dylib
│   ├── libpython3.11.dylib
│   ├── libreadline.8.dylib
│   ├── libsharpyuv.0.dylib -> PIL/.dylibs/libsharpyuv.0.dylib
│   ├── libtcl8.6.dylib
│   ├── libtiff.6.dylib -> PIL/.dylibs/libtiff.6.dylib
│   ├── libtk8.6.dylib
│   ├── libwebp.7.dylib -> PIL/.dylibs/libwebp.7.dylib
│   ├── libwebpdemux.2.dylib -> PIL/.dylibs/libwebpdemux.2.dylib
│   ├── libwebpmux.3.dylib -> PIL/.dylibs/libwebpmux.3.dylib
│   ├── libxcb.1.1.0.dylib -> PIL/.dylibs/libxcb.1.1.0.dylib
│   ├── libz.1.2.13.dylib -> PIL/.dylibs/libz.1.2.13.dylib
│   ├── models -> ../Resources/models
│   ├── notifypy
│   │   ├── example_notification_sound.wav -> ../../Resources/notifypy/example_notification_sound.wav
│   │   ├── os_notifiers
│   │   │   └── binaries
│   │   │       ├── Notificator.app -> Notificator__dot__app
│   │   │       └── Notificator__dot__app
│   │   │           └── Contents
│   │   │               ├── Info.plist -> ../../../../../../Resources/notifypy/os_notifiers/binaries/Notificator.app/Contents/Info.plist
│   │   │               ├── MacOS
│   │   │               │   └── applet
│   │   │               ├── PkgInfo -> ../../../../../../Resources/notifypy/os_notifiers/binaries/Notificator.app/Contents/PkgInfo
│   │   │               ├── Resources -> ../../../../../../Resources/notifypy/os_notifiers/binaries/Notificator.app/Contents/Resources
│   │   │               └── _CodeSignature
│   │   │                   └── CodeResources
│   │   └── py-logo.png -> ../../Resources/notifypy/py-logo.png
│   ├── objc
│   │   ├── _machsignals.cpython-311-darwin.so
│   │   └── _objc.cpython-311-darwin.so
│   ├── realesrgan-ncnn-vulkan
│   ├── tcl -> ../Resources/tcl
│   ├── theme -> ../Resources/theme
│   ├── tk -> ../Resources/tk
│   └── tkinterdnd2
│       └── tkdnd
│           └── osx-arm64
│               ├── libtkdnd2.9.3.dylib
│               ├── pkgIndex.tcl -> ../../../../Resources/tkinterdnd2/tkdnd/osx-arm64/pkgIndex.tcl
│               ├── tkdnd.tcl -> ../../../../Resources/tkinterdnd2/tkdnd/osx-arm64/tkdnd.tcl
│               ├── tkdnd_compat.tcl -> ../../../../Resources/tkinterdnd2/tkdnd/osx-arm64/tkdnd_compat.tcl
│               ├── tkdnd_generic.tcl -> ../../../../Resources/tkinterdnd2/tkdnd/osx-arm64/tkdnd_generic.tcl
│               ├── tkdnd_macosx.tcl -> ../../../../Resources/tkinterdnd2/tkdnd/osx-arm64/tkdnd_macosx.tcl
│               └── tkdnd_utils.tcl -> ../../../../Resources/tkinterdnd2/tkdnd/osx-arm64/tkdnd_utils.tcl
├── Info.plist
├── MacOS
│   └── realesrgan-gui
├── Resources
│   ├── AppKit -> ../Frameworks/AppKit
│   ├── CoreFoundation -> ../Frameworks/CoreFoundation
│   ├── Foundation -> ../Frameworks/Foundation
│   ├── PIL -> ../Frameworks/PIL
│   ├── base_library.zip
│   ├── i18n.ini
│   ├── icon-128px.png
│   ├── icon.icns
│   ├── lib-dynload -> ../Frameworks/lib-dynload
│   ├── libXau.6.0.0.dylib -> PIL/.dylibs/libXau.6.0.0.dylib
│   ├── libb2.1.dylib -> ../Frameworks/libb2.1.dylib
│   ├── libintl.8.dylib -> ../Frameworks/libintl.8.dylib
│   ├── liblcms2.2.dylib -> PIL/.dylibs/liblcms2.2.dylib
│   ├── liblzma.5.dylib -> PIL/.dylibs/liblzma.5.dylib
│   ├── libopenjp2.2.5.0.dylib -> PIL/.dylibs/libopenjp2.2.5.0.dylib
│   ├── libpython3.11.dylib -> ../Frameworks/libpython3.11.dylib
│   ├── libreadline.8.dylib -> ../Frameworks/libreadline.8.dylib
│   ├── libsharpyuv.0.dylib -> PIL/.dylibs/libsharpyuv.0.dylib
│   ├── libtcl8.6.dylib -> ../Frameworks/libtcl8.6.dylib
│   ├── libtiff.6.dylib -> PIL/.dylibs/libtiff.6.dylib
│   ├── libtk8.6.dylib -> ../Frameworks/libtk8.6.dylib
│   ├── libwebp.7.dylib -> PIL/.dylibs/libwebp.7.dylib
│   ├── libwebpdemux.2.dylib -> PIL/.dylibs/libwebpdemux.2.dylib
│   ├── libwebpmux.3.dylib -> PIL/.dylibs/libwebpmux.3.dylib
│   ├── libxcb.1.1.0.dylib -> PIL/.dylibs/libxcb.1.1.0.dylib
│   ├── libz.1.2.13.dylib -> PIL/.dylibs/libz.1.2.13.dylib
│   ├── models
│   │   ├── realesr-animevideov3-x2.bin
│   │   ├── realesr-animevideov3-x2.param
│   │   ├── realesr-animevideov3-x3.bin
│   │   ├── realesr-animevideov3-x3.param
│   │   ├── realesr-animevideov3-x4.bin
│   │   ├── realesr-animevideov3-x4.param
│   │   ├── realesrgan-x4plus-anime.bin
│   │   ├── realesrgan-x4plus-anime.param
│   │   ├── realesrgan-x4plus.bin
│   │   └── realesrgan-x4plus.param
│   ├── notifypy
│   │   ├── example_notification_sound.wav
│   │   ├── os_notifiers
│   │   │   └── binaries
│   │   │       └── Notificator.app
│   │   │           └── Contents
│   │   │               ├── Info.plist
│   │   │               ├── MacOS -> ../../../../../../Frameworks/notifypy/os_notifiers/binaries/Notificator.app/Contents/MacOS
│   │   │               ├── PkgInfo
│   │   │               └── Resources
│   │   │                   ├── Scripts
│   │   │                   │   ├── main.scpt
│   │   │                   │   └── notificator
│   │   │                   ├── applet.icns
│   │   │                   └── applet.rsrc
│   │   └── py-logo.png
│   ├── objc -> ../Frameworks/objc
│   ├── realesrgan-ncnn-vulkan -> ../Frameworks/realesrgan-ncnn-vulkan
│   ├── tcl
│   │   ├── auto.tcl
│   │   ├── clock.tcl
│   │   ├── history.tcl
│   │   ├── init.tcl
│   │   ├── package.tcl
│   │   ├── parray.tcl
│   │   ├── safe.tcl
│   │   ├── tclAppInit.c
│   │   ├── tclIndex
│   │   ├── tm.tcl
│   │   └── word.tcl
│   ├── theme
│   │   ├── dark.png
│   │   ├── light.png
│   │   └── sun-valley.tcl
│   ├── tk
│   │   ├── bgerror.tcl
│   │   ├── button.tcl
│   │   ├── choosedir.tcl
│   │   ├── clrpick.tcl
│   │   ├── comdlg.tcl
│   │   ├── console.tcl
│   │   ├── dialog.tcl
│   │   ├── entry.tcl
│   │   ├── focus.tcl
│   │   ├── fontchooser.tcl
│   │   ├── iconlist.tcl
│   │   ├── icons.tcl
│   │   ├── listbox.tcl
│   │   ├── megawidget.tcl
│   │   ├── menu.tcl
│   │   ├── mkpsenc.tcl
│   │   ├── msgbox.tcl
│   │   ├── obsolete.tcl
│   │   ├── optMenu.tcl
│   │   ├── palette.tcl
│   │   ├── panedwindow.tcl
│   │   ├── pkgIndex.tcl
│   │   ├── safetk.tcl
│   │   ├── scale.tcl
│   │   ├── scrlbar.tcl
│   │   ├── spinbox.tcl
│   │   ├── tclIndex
│   │   ├── tearoff.tcl
│   │   ├── text.tcl
│   │   ├── tk.tcl
│   │   ├── tkAppInit.c
│   │   ├── tkfbox.tcl
│   │   ├── ttk
│   │   │   ├── altTheme.tcl
│   │   │   ├── aquaTheme.tcl
│   │   │   ├── button.tcl
│   │   │   ├── clamTheme.tcl
│   │   │   ├── classicTheme.tcl
│   │   │   ├── combobox.tcl
│   │   │   ├── cursors.tcl
│   │   │   ├── defaults.tcl
│   │   │   ├── entry.tcl
│   │   │   ├── fonts.tcl
│   │   │   ├── menubutton.tcl
│   │   │   ├── notebook.tcl
│   │   │   ├── panedwindow.tcl
│   │   │   ├── progress.tcl
│   │   │   ├── scale.tcl
│   │   │   ├── scrollbar.tcl
│   │   │   ├── sizegrip.tcl
│   │   │   ├── spinbox.tcl
│   │   │   ├── treeview.tcl
│   │   │   ├── ttk.tcl
│   │   │   ├── utils.tcl
│   │   │   ├── vistaTheme.tcl
│   │   │   ├── winTheme.tcl
│   │   │   └── xpTheme.tcl
│   │   ├── unsupported.tcl
│   │   └── xmfbox.tcl
│   └── tkinterdnd2
│       └── tkdnd
│           └── osx-arm64
│               ├── libtkdnd2.9.3.dylib -> ../../../../Frameworks/tkinterdnd2/tkdnd/osx-arm64/libtkdnd2.9.3.dylib
│               ├── pkgIndex.tcl
│               ├── tkdnd.tcl
│               ├── tkdnd_compat.tcl
│               ├── tkdnd_generic.tcl
│               ├── tkdnd_macosx.tcl
│               └── tkdnd_utils.tcl
└── _CodeSignature
    └── CodeResources

50 directories, 226 files

可以看到原先macOS文件夹的文件都跑frameworks里面去了,然后应用就找不到超分可执行程序了

TransparentLC commented 1 year ago

PyInstaller 最近更新了 6.0,Changelog 里有一堆和 macOS 相关的更改。

我把 Actions 里安装 PyInstaller 的版本限制成了 5.*,看了一下现在 realesrgan-gui 应该是在 MacOS 目录里面了并且没有 Frameworks 目录,可以试一下是否可以正常使用。

hyrulelinks commented 1 year ago

PyInstaller 最近更新了 6.0,Changelog 里有一堆和 macOS 相关的更改。

我把 Actions 里安装 PyInstaller 的版本限制成了 5.*,看了一下现在 realesrgan-gui 应该是在 MacOS 目录里面了并且没有 Frameworks 目录,可以试一下是否可以正常使用。

看了changelog,这个改动是为了符合签名要求,主程序引用的可执行程序都移动到frameworks了,如果要用pyinstaller 6,define里的路径需要修改下,我假期有空了研究下看看能不能解决,如果能解决就发pr

hyrulelinks commented 1 year ago

define.py的RE_PATH修改为如下:

FRA_PATH = os.path.join(os.path.dirname(APP_PATH), 'Frameworks')

# 判断操作系统类型
if os.name == 'nt':  # Windows
    RE_PATH = os.path.join(APP_PATH, 'realesrgan-ncnn-vulkan.exe')
else:  # macOS or other platforms
    RE_PATH = os.path.join(FRA_PATH, 'realesrgan-ncnn-vulkan')

main.py的models路径修改为如下:

class REGUIApp(ttk.Frame):
    def __init__(self, parent: tk.Tk):
        super().__init__(parent)
        if os.name == 'nt':  # Windows
            modelFiles = set(os.listdir(os.path.join(define.APP_PATH, 'models')))
        else:  # macOS or other platforms
            modelFiles = set(os.listdir(os.path.join(define.FRA_PATH, 'models')))
            self.models = sorted(
                x for x in set(os.path.splitext(y)[0] for y in modelFiles)
                if f'{x}.bin' in modelFiles and f'{x}.param' in modelFiles
            )
            for m in (
                'realesrgan-x4plus',
                'realesrgan-x4plus-anime',
            )[::-1]:
                try:
                    self.models.insert(0, self.models.pop(self.models.index(m)))
                except ValueError:
                    pass
            self.modelFactors: dict[str, int] = {}
            for m in self.models:
                self.modelFactors[m] = 4
                if s := re.search(r'(\d+)x|x(\d+)', m):
                    self.modelFactors[m] = int(s.group(1) or s.group(2))

            self.downsample = (
                ('Lanczos', Image.Resampling.LANCZOS),
                ('Bicubic', Image.Resampling.BICUBIC),
                ('Hamming', Image.Resampling.HAMMING),
                ('Bilinear', Image.Resampling.BILINEAR),
                ('Box', Image.Resampling.BOX),
                ('Nearest', Image.Resampling.NEAREST),
            )
            self.tileSize = (0, 32, 64, 128, 256, 512, 1024)

            self.config = configparser.ConfigParser({
                'ResizeMode': int(param.ResizeMode.RATIO),
                'ResizeRatio': 4,
                'ResizeWidth': 1024,
                'ResizeHeight': 1024,
                'Model': self.models[0],
                'DownsampleIndex': 0,
                'GPUID': -1,
                'TileSizeIndex': 0,
                'LossyQuality': 80,
                'UseWebP': False,
                'UseTTA': False,
                'OptimizeGIF': False,
                'LossyMode': False,
                'IgnoreError': False,
                'CustomCommand': '',
            })
            self.config['Config'] = {}
            self.config.read(define.APP_CONFIG_PATH)

            self.outputPathChanged = True
            self.logPath = os.path.join(define.APP_PATH, 'output.log')
            self.logFile: typing.IO = None

            self.setupVars()
            self.setupWidgets()

task.py的cmd部分参考了 https://github.com/TransparentLC/realesrgan-gui/issues/4#issuecomment-1177681886 改为下面:

            cmd = (
                define.RE_PATH,
                '-v',
                '-i', inputPath,
                '-o', outputPath,
                '-s', str(self.config.modelFactor),
                '-t', str(self.config.tileSize),
                '-n', self.config.model,
                '-g', 'auto' if self.config.gpuID < 0 else str(self.config.gpuID),
                ('-x' if self.config.useTTA else ''),
            )
            if os.name == 'nt':  # Windows
                os.chdir(define.APP_PATH)
            else:  # macOS or other platforms
                os.chdir(define.FRA_PATH)
                with subprocess.Popen(
                    cmd,
                    stderr=subprocess.PIPE,
                    universal_newlines=True,

上面这样修改完后用pyinstaller 6.0打包后得到的应用可以正常得到放大的图像

截屏2023-10-02 02 55 12

但放大后还是会跳报错窗口(用终端运行主程序并未提示错误,但报错窗口依然出现)

截屏2023-10-02 02 54 55

尝试了各种能想到的办法,依然没有解决,请作者帮忙看下问题出在哪里,谢谢! @TransparentLC

TransparentLC commented 1 year ago

我不了解 macOS,所以也不知道这个 -192 是怎么回事(最多只能搜索到“Resource not found”的解释),也许你可以再尝试确定一下是哪一行弄出这个 -192 的。

不过这个修改有两个很明显的问题:

  1. 判断是否涉及到 Frameworks 目录的条件应该是“在 macOS 下运行”和“使用 PyInstaller 打包”(也就是 hasattr(sys, '_MEIPASS')),而不是“不在 Windows 下运行”(不然还有 Linux 呢?)
  2. else: # macOS or other platforms 这个分支以后的代码的缩进全都多了一层,在 Windows 下就不会执行了

顺便一提,在 Markdown 里可以用语言为 diff 的代码块在相关行前面写上 +- 标出删改的区域 :

foo
-bar
+baz
qux
hyrulelinks commented 1 year ago
-APP_PATH = os.path.dirname(os.path.realpath(sys.executable if hasattr(sys, '_MEIPASS') else __file__))
+APP_PATH = os.path.realpath(sys._MEIPASS) if getattr(sys, 'frozen', False) else os.path.dirname(os.path.realpath(__file__))

最新仓库其他都不改,只改了define里面的APP_PATH定义,再用pyinstaller 6.0打包,realesrgan_ncnn_vulkan依然在Frameworks文件夹,models依然在resources文件夹,但运行程序不会再提示找不到realesrgan_ncnn_vulkan,猜测原来APP_PATH的定义路径固化成realeargan_gui所在路径了,pyinstaller打包后,realesrgan_ncnn_vulkan和models都不在同一路径了,于是就无法找到了。 运行程序放大图片可以获得放大后图像,除了会跳出下面这个-192错误提示外,一切正常。 错误 OSStatus -192 是一个macOS错误代码,通常表示文件或资源未找到。目前猜测是修改了APP_PATH定义后,原本放大程序完成图像放大并保存放大结果图像后,还有什么执行任务因为找不到文件或资源然后报错。 能力不足实在找不到放大图像后还有什么任务是需要找文件或资源的,作者能否帮忙看看,谢谢! @TransparentLC

TransparentLC commented 1 year ago

猜测原来APP_PATH的定义路径固化成realeargan_gui所在路径了

确实是这么设计的,假定 GUI 和程序放在同一个路径下。

如果按你测试的话直接进行 x4 放大不进行有损压缩和 downsample 的话放大流程是这个样子:原图 x2 放大到临时文件 A,临时文件 A 再 x2 放大到临时文件 B 然后 os.remove 删除上一个临时文件 A(当然用 x4 模型的话就只要放大一次了),用 shutil.move 把临时文件 B 移动到输出路径。这部分就是 task.py 里面的 RESpawnTask。临时文件都放在 tempfile.gettempdir() 获取的路径下,应该不会受打包影响。

hyrulelinks commented 1 year ago

python刚自学入门,不知道怎么解决了,去问了AI,给出下面的回答我也看不懂到底对还是不对,按照这个回答感觉要修改的地方太多了,可能越改问题越多,超出我的能力了😭 @TransparentLC

从提供的main.py代码来看,退出时弹出OSStatus -192错误很可能是资源没有被正确释放导致的。

我注意到一些可能的问题:

  1. 你在启动任务线程后,并没有保证主线程等待任务线程完成后再退出。所以主线程直接退出了,而任务线程可能还在后台运行。

  2. 任务线程中在完成回调里面没有做任何资源释放,如关闭打开的文件等。

  3. 主线程直接调用root.destroy()退出,没有优雅地关闭后台线程。

  4. 没有使用try-finally或with语句块确保文件、网络连接等资源被关闭。

建议尝试以下修改:

  1. 在启动任务线程前,保留对线程对象的引用,比如:task_thread = threading.Thread(...)

  2. 在主线程里加一个task_thread.join(),确保等待线程结束。

  3. 在任务线程完成回调中加入关闭文件,网络连接等操作。

  4. 用try-finally确保资源释放,或者使用with语句块。

  5. 主线程退出前使用线程的名的is_alive()判断后台线程是否还在运行。

  6. 可以调用task_thread.terminate()来终止线程。

  7. 调用sys.exit()而不是直接root.destroy()

这些改进应该可以避免一些资源泄露问题,从而避免退出时出现错误。具体需要根据你的线程和资源使用情况调整。

好的,根据我们之前的分析,需要修改main.py中的以下代码:

  1. 在启动任务线程前,新增任务线程的引用:
# 新增
task_thread = None
  1. 启动任务线程时,将线程对象赋值给task_thread:
# 第166行左右
task_thread = threading.Thread(
  target=task.taskRunner,
  args=(
     ...
  )
)
task_thread.start()
  1. 在主线程退出前,加入线程等待和判断:
# 在root.destroy()前
if task_thread and task_thread.is_alive():
  task_thread.join()
  1. 在任务完成回调中关闭文件:
# 第145行左右
def completeCallback(withError: bool):
  ...
  if self.logFile: 
    self.logFile.close()
  1. 使用sys.exit()正常退出:
# 替换最后一句
root.destroy()
sys.exit(0)

具体需要将上面示意代码插入合适的位置,比如task_thread的声明需要放在启动线程之前。

这些改动可以让主线程等待任务线程结束,确保资源如文件被关闭,并正常退出程序。

让我知道如果这个改动建议能帮你解决问题!

TransparentLC commented 1 year ago

并没有保证主线程等待任务线程完成后再退出……主线程直接调用 root.destroy() 退出……

对于 tk 的程序来说退出主线程就是关闭程序,也就是按右上角的 X,如果要自定义关闭前做些什么的话(比如这里需要保存 config)就重写 WM_DELETE_WINDOW 最后再 root.destroy()

https://github.com/TransparentLC/realesrgan-gui/blob/f8eb23ba3d60049ebe61fa6f69d9eef35d6626a8/main.py#L496-L499

但是显然也不是退出程序的时候才出现 -192。

没有做任何资源释放……没有使用 try-finally 或 with 语句块确保文件、网络连接等资源被关闭……在任务完成回调中关闭文件……

https://github.com/TransparentLC/realesrgan-gui/blob/f8eb23ba3d60049ebe61fa6f69d9eef35d6626a8/main.py#L383

这个关闭文件写在 finallyCallback 里,不论中途是否出现错误最后 return 前都会执行。

https://github.com/TransparentLC/realesrgan-gui/blob/f8eb23ba3d60049ebe61fa6f69d9eef35d6626a8/task.py#L291-L306

hyrulelinks commented 1 year ago

找不出原因,可能是pyinstaller6自己的问题,放弃了,还是老实用pyinstaller5好了

hyrulelinks commented 1 year ago

pyinstaller 6.x下好像是notificator的原因导致OSStatus Error -192报错,请问如何把notify模块从源码删除,我再打包试试看 @TransparentLC

TransparentLC commented 1 year ago

其他系统还是要用提醒功能的,这怎么删(

现在是把这个的 import 写进了 try except,这样也不行吗?

~https://github.com/TransparentLC/realesrgan-gui/blob/master/main.py#L479~

↑我记错了,这个是深色模式相关的

hyrulelinks commented 1 year ago

其他系统还是要用提醒功能的,这怎么删(

现在是把这个的 import 写进了 try except,这样也不行吗?

master/main.py#L479

pyinstaller 6.x 用2023年2月份的commit(加入notify前)之前的仓库打包试了,打包后运行正常了,实锤是notify模块的问题

能否改成windows有提醒功能,mac没有提醒功能?notify这个模块使用notify.app来实现的,之前pyinstaller 5.x的时候虽然没有报错OSStatus Error -192,但实际也并从未发挥过作用,(有一次发挥作用问我要权限,不给就没作用,给的话mac下权限控制比较严格,不建议用这种app里套app的方式)现在pyinstaller 6.x报错了,感觉这个模块在mac下有些鸡肋了,希望能用if的方式取消mac的notify

另外就是找不到realesrgan主程序和model的问题,define.py修改如下可以解决:

BASE_PATH = os.path.dirname(os.path.realpath(__file__))
APP_PATH = os.path.dirname(os.path.realpath(__file__))
RE_PATH = os.path.join(APP_PATH, 'realesrgan-ncnn-vulkan' + ('.exe' if os.name == 'nt' else ''))

这样改算是返璞归真了,从源码运行和pyinstaller打包运行都可以,没出现新的问题,但这么改我是蒙的,不确定这样是否与项目原来的define的目的一致,windows上我没试过这样改了之后会否有问题

@TransparentLC

TransparentLC commented 1 year ago

那就把那个 import 加到 if sys.platform == 'darwin': 里面,然后 requirements.txt 也可以跟着改一下。

一开始的设计是 BASE_PATH 是 repo 的路径(源码运行)或运行打包的 onefile exe 时自解压的临时目录 _MEI****APP_PATHmain.py 所在的路径(源码运行,实际上还是 repo 路径)或 exe 所在的路径,你这么改应该是有问题的,当然你可以加各种判断,比如既是 macOS 又是打包的情况下路径就是...

hyrulelinks commented 1 year ago

那就把那个 import 加到 if sys.platform == 'darwin': 里面,然后 requirements.txt 也可以跟着改一下。

一开始的设计是 BASE_PATH 是 repo 的路径(源码运行)或运行打包的 onefile exe 时自解压的临时目录 _MEI****APP_PATHmain.py 所在的路径(源码运行,实际上还是 repo 路径)或 exe 所在的路径,你这么改应该是有问题的,当然你可以加各种判断,比如既是 macOS 又是打包的情况下路径就是...

mac用的.spec是pyinstaller -D -w方式打包的,如果Windows是pyinstaller -F -w方式打包的话确实会有问题,realesrgan会在临时文件夹里,这个项目用onefile效率比较差,因为realesrgan和模型体积较大,每次运行都要自解压先,-D方式效率会高些,几乎没延迟

我明天按上面的改下看看能不能解决问题

TransparentLC commented 1 year ago

这个项目用onefile效率比较差,因为realesrgan和模型体积较大,每次运行都要自解压先

按照设计的话,这两个是放在 APP_PATH 的目录,并不需要自解压。

hyrulelinks commented 1 year ago

可能mac和windows下不太一样,mac下如果onefile会把realesrgan和models打包进main主程序,运行时需要先自解压到临时文件夹