斗争是真实的
当我开始研究这个主题时,我很快就意识到大多数指南,教程和stackoverflow答案只有部分信息或直接提供不良建议,这会阻止您在Apple的App Store上发布应用程序。 p>
我不得不拼命所有这些,并最终能够将Python解释器嵌入MacOS应用程序,完全签名并具有发布到App Store的能力。
因此,这里是关于如何将Python解释器嵌入您的应用程序的快速简单指南。当您有明确的步骤时,这真的很简单。
我们为什么还需要这个?
作为本地Apple Eco System开发人员(如今我主要是iOS),我相信Swift是为iOS和MACOS开发的唯一方法。
但是,有时您的应用程序需要您不想重塑的大事,并且仅在Python中可用。那为什么不使用呢?
python有很多工具和开源代码,您可以直接使用框,可以通过惊人的功能赋予您的应用程序功能,并且您可以轻松地从Swift调用Python代码。
但要小心,通过将python解释器嵌入您的二进制文件中,您将其放大约100MB。因此,我不建议您使用Swift或找到维护良好的SPM的简单内容。
您可以在App Store上发布此类MacOS应用吗?
是。您可以嵌入Python并发布到MacOS App Store。
虽然MacOS已经随附Python,但您不想使用它。
- 您不能依靠系统上安装的python版本。
- 这将需要您删除MacOS应用程序的沙盒和
Disable Library Validation
。一旦这样做,您就无法将应用程序提交给App Store,甚至可能在App Store外面的公证化问题:https://developer.apple.com/documentation/security/notarizing_macos_software_before_distribution
另一方面,通过嵌入Python解释器,您也允许应用程序的Python部分签名。
这允许硬化的运行时间保持完整:
- 无需删除沙箱 - 您需要它才能将MacOS应用程序提交到App Store。
- 不需要
Disable Library Validation
。
那iOS呢?
是。您可以嵌入Python并发布到iOS App Store。只要看pyto:https://pyto.app
iOS App Store对此没有限制。所有这些都签名为一个应用程序。
将Python嵌入iOS的过程与MACOS非常相似,但是它可能需要在以后的文章中涵盖的更多步骤。
逐步嵌入MacOS应用中的Python解释器
-
添加pythonkit spm:
https://github.com/pvieito/PythonKit. -
下载所需Python版本的框架(用于MacOS平台):
https://github.com/beeware/Python-Apple-support -
从
tag.gz
存档中提取python-stdlib
和Python.xcframework
。 -
将它们复制到MacOS应用程序的根,最好通过Xcode。
-
Xcode General->框架:
5.1。应该已经在那里:
-Python.xcframework
被设置为Do Not Embed
-PythonKit
5.2。添加其他必需框架:
-SystemConfiguration.framework
设置为Do Not Embed
-
xcode
Build Phases
:
6.1。验证Copy Bundle Resources
包含python-stdlib
。
6.2。添加bash脚本以在python-stdlib/lib-dynload/
中签名.so
二进制文件:
重要说明:.so
二进制文件必须与您的TeamID签名,如果您需要使用Sign and Run Locally
,它将被签名为Ad-Hoc,并且您需要kude0。
set -e
echo "Signing as $EXPANDED_CODE_SIGN_IDENTITY_NAME ($EXPANDED_CODE_SIGN_IDENTITY)"
find "$CODESIGNING_FOLDER_PATH/Contents/Resources/python-stdlib/lib-dynload" -name "*.so" -exec /usr/bin/codesign --force --sign "$EXPANDED_CODE_SIGN_IDENTITY" -o runtime --timestamp=none --preserve-metadata=identifier,entitlements,flags --generate-entitlement-der {} \;
- 创建一个名为
module.modulemap
的文件,并具有以下代码:
module Python {
umbrella header "Python.h"
export *
link "Python"
}
-
将
module.modulemap
文件放在Python.xcframework/macos-arm64_x86_64/Headers/
中。
这将使我们可以做import Python
-
在运行时至INIT PYTHON,尽早:
import Python
guard let stdLibPath = Bundle.main.path(forResource: "python-stdlib", ofType: nil) else { return }
guard let libDynloadPath = Bundle.main.path(forResource: "python-stdlib/lib-dynload", ofType: nil) else { return }
setenv("PYTHONHOME", stdLibPath, 1)
setenv("PYTHONPATH", "\(stdLibPath):\(libDynloadPath)", 1)
Py_Initialize()
// we now have a Python interpreter ready to be used
- 运行测试代码:
import PythonKit
let sys = Python.import("sys")
print("Python Version: \(sys.version_info.major).\(sys.version_info.minor)")
print("Python Encoding: \(sys.getdefaultencoding().upper())")
print("Python Path: \(sys.path)")
_ = Python.import("math") // verifies `lib-dynload` is found and signed successfully
- 我们从事业务。现在,我们可以添加我们想要的任何Python代码。
要集成第三方Python代码和依赖项,您将需要确保
PYTHONPATH
包含其路径;然后您可以做Python.import(" <SOME LIB> ")
。 有时,Python代码可能太复杂了,无法与Swift打电话给Pythonkit,因此我的建议是编写一个小的Python脚本,然后从Swift中调用该脚本的方法。
祝你好运。
^(;,;)^
更新:
我已经提交了上述步骤,以成为Beeware Python-Apple-Support的官方用法指南。如果您在上述步骤上遇到麻烦,则使用指南可能包含其他信息:https://github.com/beeware/Python-Apple-support/blob/main/USAGE.md。