使用 pyinstaller 创建的 Mac 应用程序无法使用参数

问题描述 投票:0回答:1

我的 python 代码在控制台中运行良好。它加载给定的 Excel 文件并使用 openpyxl 将一些数据写入其中:

try:
    # process given excel file
    PLIK = sys.argv[1]
    process_the_file(PLIK) # my function
except IndexError:
    print('No file to process')

我想用在 Mac 系统上运行的脚本制作一个应用程序。我尝试像这样使用 pyinstaller:

>>> pyi-makespec my_script.py --onedir --windowed --argv-emulation --icon logo.icns --osx-bundle-identifier com.comp.my.script --name The_Script

创建 .spec 文件后,我在其中添加 Mac 所需的数据:

info_plist={
    'NSPrincipalClass': 'NSApplication',
    'NSAppleScriptEnabled': False,
    'CFBundleDocumentTypes': [{
           'CFBundleTypeName': "XLSX input table document",
           'CFBundleTypeExtensions': [
                'xlsx',
           ],
           'CFBundleTypeRole': "Editor",
           'LSItemContentTypes': [
                'com.microsoft.excel.xls'
           ],
           'LSHandlerRank': 'Owner'
      }],
 }

我运行命令来创建应用程序:

>>> pyinstaller The_Script.spec

现在我尝试将应用程序与 example.xslx 文件一起使用。我单击 example.xlsx 文件以使用 The_Script.app 打开它,但它不起作用 - 在调试中我看到消息“没有要处理的文件”。就像应用程序看不到我传递的参数一样。 我这样调试:

>>> open dist/The_Script.app/Contents/MacOS/The_Script --args example.xlsx

我想我阅读了所有文档和互联网,但我不知道出了什么问题。

环境:

macOS Sonoma 14.4
Python 3.9.6
pyinstaller 6.4.0
macos pyinstaller
1个回答
0
投票

主要问题是

--argv_emulation
的作用非常有限。它允许您将文档直接拖到应用程序包上,然后打开该文档。但如果您的应用程序已经打开,即使这样也不起作用。正如您所观察到的,它不适用于从文档本身的上下文菜单打开您的应用程序。 在 pyinstaller 文档中阅读更多相关信息

更全面的解决方案需要拦截苹果事件。如果您可以使事件拦截起作用,请不要使用

--argv_emulation
。 详细信息取决于您制作应用程序的具体方式:

  1. 如果您使用

    tkinter
    作为 GUI 工具包,请使用
    ::tk::mac::OpenDocument
    命令注册您的回调。 (我个人没有使用过这个技术)

  2. 如果您使用 PySide/PyQt 作为 GUI 工具包,请拦截 QFileOpenEvent 并将其转发到您的回调。在 PySide6 中:

class MyApplication(QApplication):
    def event(self, event):
        # Intercept Mac file open events
        if event.type() == QEvent.FileOpen:
            self.on_file_open_event.emit(event.file())
        return super().event(event)

    on_file_open_event = QtCore.Signal(str)

app = MyApplication()

...

app.on_file_open_event.connect(my_load_file_slot)

...

sys.exit(app.exec())
  1. 如果你使用其他GUI工具包,可能有办法,但我不知道细节。
© www.soinside.com 2019 - 2024. All rights reserved.