我使用 PyInstaller 构建到可执行文件中的脚本遇到问题。该脚本在作为 Python 脚本运行时运行良好,但在作为 PyInstaller 应用程序运行时,遇到路径超过 260 个字符的文件时会失败。
我知道这是由于Windows 的限制,并且必须在注册表和使用启用该设置的应用程序清单中选择对更长路径的支持。longPathAware
顺便说一句,这在 Python 本身中起作用的原因是因为在 Python 3.6 中,开发人员为python.exe
和启用了此设置pythonw.exe
。
到目前为止,我已经完成了所有这些工作,如果我将以下清单文件放在构建的 PyInstaller 应用程序旁边(使用--onefile
模式),它确实可以工作:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware>
</windowsSettings>
</application>
</assembly>
但是,为了让最终用户的应用程序独立且可移植,我试图避免使用外部清单文件,而是让 PyInstaller 将此自定义清单嵌入到可执行文件中。
该--manifest
选项据称是这样做的——至少从 PyInstaller 3.5 开始,根据更改日志和PR #3746:
但是,当指定时,自定义清单文件似乎被忽略了,因为应用程序在没有外部清单文件的情况下继续在长路径上失败,并且在--onedir
模式下检查捆绑的清单文件,它看起来就像它忽略了自定义一个并创建这个代替:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<dependency>
<dependentAssembly>
<assemblyIdentity language="*" name="Microsoft.Windows.Common-Controls" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" type="win32" version="6.0.0.0"/>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"/>
</dependentAssembly>
</dependency>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
</application>
</compatibility>
</assembly>
我做错了什么或理解错了吗?该--manifest
选项不符合我的想法吗?这是一个错误吗?
这个答案描述了修改 PyInstaller 源代码以覆盖嵌入式清单创建。这还有必要吗?
我还在 GitHub 上遇到了一个似乎有同样问题的项目;此 PR的作者指出:
请注意,PyInstaller 还不了解该
longPathAware
设置并将其从清单中删除。
我不知道这是否属实,但我认为它确实为这是一个错误提供了一些分量。
我正在使用 PyInstaller 3.6、Python 3.7.2 和 Windows 10 版本 1809。