Mac M3 Sonoma下py2app打包Azure Speech SDK程序提示找不到azure模块
问题:py2app打包Python应用时无法识别Azure Speech SDK模块
环境:Mac OS M3 Pro Sonoma,使用Poetry管理依赖,Azure Speech SDK版本1.41.1,尝试用py2app将基于Tkinter的Python程序打包成.dmg文件,运行构建时报错No module named 'azure'。
原setup.py代码
import sys import os import site from typing import List, Dict, Any APP_NAME: str = 'app' VERSION: str = '1.0.0' MIN_PYTHON_VERSION: str = '>=3.13' REQUIRED_PACKAGES: List[str] = [ 'azure-cognitiveservices-speech>=1.41.1', 'python-dotenv>=0.19.0', ] SETUP_REQUIRES: List[str] = [ 'py2app', 'setuptools>=44.0.0', 'azure-cognitiveservices-speech>=1.41.1', ] # Add Azure SDK import at module level with error handling try: import azure.cognitiveservices.speech as speech_sdk SPEECH_SDK_PATH = os.path.dirname(speech_sdk.__file__) AZURE_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(SPEECH_SDK_PATH))) except ImportError: SPEECH_SDK_PATH = None print("Warning: Azure Speech SDK not found. Build may be incomplete.") def log_environment_info() -> None: """Log environment information for debugging purposes. Raises: ImportError: If azure speech SDK cannot be imported """ print("Python interpreter being used:", sys.executable) print("Python path:", sys.path) print("Site packages:", site.getsitepackages()) try: # List all files in the azure package directory azure_dir = os.path.dirname(os.path.dirname(os.path.dirname(speech_sdk.__file__))) print("Contents of azure package directory:") for root, dirs, files in os.walk(azure_dir): print(f"Directory: {root}") for file in files: print(f" - {file}") except ImportError as e: print("Import Error:", str(e)) raise # Call this before setup() log_environment_info() APP = ['app.py'] DATA_FILES = [ 'requirements.txt', 'settings.ini', '.venv', 'languages.json', ] # Get the site-packages directory and package paths SITE_PACKAGES = site.getsitepackages()[0] AZURE_PATH = os.path.join(SITE_PACKAGES, 'azure') AZURE_SPEECH_PATH = os.path.join(SITE_PACKAGES, 'azure', 'cognitiveservices', 'speech') OPTIONS: Dict[str, Any] = { 'argv_emulation': True, 'includes': [ 'azure', 'azure.cognitiveservices', 'azure.cognitiveservices.speech', ], 'packages': [ 'azure', 'azure.cognitiveservices', 'azure.cognitiveservices.speech', ], 'site_packages': True, 'resources': [ AZURE_ROOT, # Include the entire azure package SPEECH_SDK_PATH, # Include the speech SDK specifically ], 'frameworks': [], 'plist': { 'CFBundleName': 'App', 'CFBundleShortVersionString': '1.0.0', 'CFBundleVersion': '1.0.0', 'CFBundleIdentifier': 'com.yourdomain.domain', 'NSMicrophoneUsageDescription': 'test app', 'LSMinimumSystemVersion': '10.10', } } setup( name=APP_NAME, version=VERSION, packages=find_packages(), app=APP, data_files=DATA_FILES, options={'py2app': OPTIONS}, setup_requires=SETUP_REQUIRES, install_requires=REQUIRED_PACKAGES, python_requires=MIN_PYTHON_VERSION, description='Kasana Application', long_description=open('README.md').read(), long_description_content_type='text/markdown', author='Your Name', author_email='your.email@example.com', url='https://github.com/yourusername/app', classifiers=[ 'Development Status :: 5 - Production/Stable', 'Intended Audience :: Developers', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.13', ], )
报错栈信息
1120 total 42 filtered 150 orphaned 1078 remaining PACKAGE DIRECTORY /Users/sethhammock/Code/Repos/kasana-production/azure PACKAGE DIRECTORY /Users/sethhammock/Code/Repos/kasana-production/.venv/lib/python3.11/site-packages/azure/azure PACKAGE DIRECTORY /Users/sethhammock/Code/Repos/kasana-production/azure PACKAGE DIRECTORY /Users/sethhammock/.pyenv/versions/3.11.6/lib/python311.zip/azure PACKAGE DIRECTORY /Users/sethhammock/.pyenv/versions/3.11.6/lib/python3.11/azure PACKAGE DIRECTORY /Users/sethhammock/.pyenv/versions/3.11.6/lib/python3.11/lib-dynload/azure PACKAGE DIRECTORY /Users/sethhammock/Code/Repos/kasana-production/.venv/lib/python3.11/site-packages/azure PACKAGE DIRECTORY /Users/sethhammock/Code/Repos/kasana-production/.venv/lib/python3.11/site-packages/setuptools/_vendor/azure Traceback (most recent call last): File "/Users/sethhammock/Code/Repos/kasana-production/setup.py", line 135, in <module> setup( File "/Users/sethhammock/Code/Repos/kasana-production/.venv/lib/python3.11/site-packages/setuptools/__init__.py", line 117, in setup return distutils.core.setup(**attrs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/sethhammock/Code/Repos/kasana-production/.venv/lib/python3.11/site-packages/setuptools/_distutils/core.py", line 183, in setup return run_commands(dist) ^^^^^^^^^^^^^^^^^^ File "/Users/sethhammock/Code/Repos/kasana-production/.venv/lib/python3.11/site-packages/setuptools/_distutils/core.py", line 199, in run_commands dist.run_commands() File "/Users/sethhammock/Code/Repos/kasana-production/.venv/lib/python3.11/site-packages/setuptools/_distutils/dist.py", line 954, in run_commands self.run_command(cmd) File "/Users/sethhammock/Code/Repos/kasana-production/.venv/lib/python3.11/site-packages/setuptools/dist.py", line 999, in run_command super().run_command(command) File "/Users/sethhammock/Code/Repos/kasana-production/.venv/lib/python3.11/site-packages/setuptools/_distutils/dist.py", line 973, in run_command cmd_obj.run() File "/Users/sethhammock/Code/Repos/kasana-production/.venv/lib/python3.11/site-packages/py2app/build_app.py", line 987, in run self._run() File "/Users/sethhammock/Code/Repos/kasana-production/.venv/lib/python3.11/site-packages/py2app/build_app.py", line 1217, in _run self.run_normal() File "/Users/sethhammock/Code/Repos/kasana-production/.venv/lib/python3.11/site-packages/py2app/build_app.py", line 1329, in run_normal pkgdirs = self.collect_packagedirs() ^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/sethhammock/Code/Repos/kasana-production/.venv/lib/python3.11/site-packages/py2app/build_app.py", line 1293, in collect_packagedirs [ File "/Users/sethhammock/Code/Repos/kasana-production/.venv/lib/python3.11/site-packages/py2app/build_app.py", line 1294, in <listcomp> os.path.join(os.path.realpath(self.get_bootstrap(pkg)), "") ^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/sethhammock/Code/Repos/kasana-production/.venv/lib/python3.11/site-packages/py2app/build_app.py", line 2205, in get_bootstrap bootstrap = imp_find_module(bootstrap)[1] ^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/sethhammock/Code/Repos/kasana-production/.venv/lib/python3.11/site-packages/modulegraph/util.py", line 34, in imp_find_module result = imp.find_module(name, path) ^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/sethhammock/.pyenv/versions/3.11.6/lib/python3.11/imp.py", line 298, in find_module raise ImportError(_ERR_MSG.format(name), name=name) ImportError: No module named 'azure'
解决方案
1. 修正Python版本不一致问题
setup.py中指定的MIN_PYTHON_VERSION为>=3.13,但实际使用的Python版本是3.11.6,版本不匹配会导致依赖识别异常。将MIN_PYTHON_VERSION修改为>=3.11,同时更新classifiers中的Python版本:
MIN_PYTHON_VERSION: str = '>=3.11' # ... classifiers=[ # ... 'Programming Language :: Python :: 3.11', ],
2. 移除干扰性目录
- 从
DATA_FILES中删除.venv,虚拟环境目录无需打包,反而会干扰py2app的路径识别:
DATA_FILES = [ 'requirements.txt', 'settings.ini', 'languages.json', ]
- 检查项目根目录是否存在名为
azure的文件夹(报错中显示/Users/sethhammock/Code/Repos/kasana-production/azure),如果这不是Python包,直接删除该文件夹,避免py2app误识别。
3. 调整py2app配置,排除冲突模块
修改OPTIONS配置,移除冗余的resources路径,添加excludes排除干扰的azure目录,同时精简includes和packages到实际需要的模块:
OPTIONS: Dict[str, Any] = { 'argv_emulation': True, 'includes': [ 'azure.cognitiveservices.speech', 'python_dotenv', ], 'packages': [ 'azure.cognitiveservices.speech', ], 'site_packages': True, 'excludes': [ 'setuptools._vendor.azure', ], 'plist': { 'CFBundleName': 'App', 'CFBundleShortVersionString': '1.0.0', 'CFBundleVersion': '1.0.0', 'CFBundleIdentifier': 'com.yourdomain.domain', 'NSMicrophoneUsageDescription': 'test app', 'LSMinimumSystemVersion': '10.10', } }
4. 修正Azure路径计算错误
原代码中AZURE_ROOT的路径计算多了一层dirname,导致指向site-packages而非azure包目录,修正为:
try: import azure.cognitiveservices.speech as speech_sdk SPEECH_SDK_PATH = os.path.dirname(speech_sdk.__file__) AZURE_ROOT = os.path.dirname(os.path.dirname(SPEECH_SDK_PATH)) # 仅两次dirname,指向azure包根目录 except ImportError: SPEECH_SDK_PATH = None print("Warning: Azure Speech SDK not found. Build may be incomplete.")
5. 调整packages参数
如果项目根目录没有自定义Python包,将setup中的packages=find_packages()改为packages=[],避免py2app误识别无关目录:
setup( # ... packages=[], # ... )
6. 正确使用Poetry虚拟环境打包
运行打包命令时,确保使用Poetry的虚拟环境:
poetry run python setup.py py2app
内容的提问来源于stack exchange,提问作者serxio
相关产品推荐
相关产品推荐

