在 PyInstaller 应用程序中启用 Windows 长文件路径支持

Enabling Windows long file path support in PyInstaller application

我运行正在使用 PyInstaller 内置到可执行文件中的脚本遇到问题。当 运行 作为 Python 脚本时脚本工作正常,但是当 运行 作为 PyInstaller 应用程序时,当它遇到路径超过 260 个字符的文件时它会失败。

我知道这是因为 python.exepythonw.exelimitation of Windows and support for longer paths must be opted into both in the registry and using an application manifest which enables the longPathAware setting. Incidentally, the reason this works in Python itself is because at Python 3.6 the developers enabled this setting

到目前为止,我已经完成了所有这些工作,如果我将以下清单文件与构建的 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 option purportedly does this -- at least since PyInstaller 3.5, per the changelog and PR #3746:

  • (Windows) Fix UAC in one-file mode by embedding the manifest. (#1729, #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 选项是否不符合我的想法?这是一个错误吗?

This answer 描述了修改 PyInstaller 源代码以覆盖嵌入式清单创建。这还有必要吗?

我在 GitHub 上也遇到了一个似乎有同样问题的项目; this PR 的作者声明:

Note that PyInstaller does not understand the longPathAware setting yet and strips it out of the manifest.

我不知道这是不是真的,但我认为这确实是一个错误。

我正在使用 PyInstaller 3.6、Python 3.7.2 和 Windows 10 版本 1809。

现在在 PyInstaller 4.2 中实现了:https://pyinstaller.readthedocs.io/en/v4.2/CHANGES.html

(Windows) Enable longPathAware option in built application’s manifest in order to support long file paths on Windows 10 v.1607 and later. (#5424)