【问题标题】:Enabling Windows long file path support in PyInstaller application在 PyInstaller 应用程序中启用 Windows 长文件路径支持
【发布时间】:2020-05-01 16:03:26
【问题描述】:

我在使用 PyInstaller 构建到可执行文件中的脚本遇到问题。该脚本在作为 Python 脚本运行时运行良好,但在作为 PyInstaller 应用程序运行时,遇到路径超过 260 个字符的文件时会失败。

我知道这是由于limitation of Windows 和对更长路径的支持必须在注册表中使用opted into 并使用启用longPathAware 设置的应用程序清单。顺便说一句,这在 Python 本身中起作用的原因是因为 at Python 3.6 the developers enabled this setting 用于 python.exepythonw.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 option 据称是这样做的——至少从 PyInstaller 3.5 开始,根据 changelogPR #3746

  • (Windows) 通过嵌入清单将 UAC 修复为单文件模式。 (#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 的作者说:

请注意,PyInstaller 还不理解 longPathAware 设置并将其从清单中删除。

我不知道这是否属实,但我认为它确实为这是一个错误提供了一些分量。

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

【问题讨论】:

  • 您的程序真的只应该在注册表中启用长 DOS 路径的 Windows 10 系统中的长路径下正常工作吗?也许您应该考虑规范化以使用 "\\?\" 扩展路径,这允许使用长路径一直到 Windows NT 4 (1996)。
  • @ErykSun 是的,我已经阅读了有关该前缀的信息,但它似乎有其自身的兼容性问题(此外,它的目的不是专门用于启用长路径,而是禁用对路径字符串的解析)。在我的例子中,这个程序只能被 Windows 10 电脑使用,我们可以为它使用组策略。但是我也对此感兴趣,因为还有其他有用的东西可以放在 PyInstaller 应该支持的清单中,或者至少允许在不覆盖它们的情况下,例如dpiAware。至少可以使用外部清单,所以不会太繁琐,只是不太理想。
  • 嵌入时,应用程序清单只是一个 PE 资源。您可以在文件中将其替换为后续构建步骤 - 至少在 PyInstaller 得到修复之前。
  • 我考虑过,但显然在 PyInstaller 应用程序上使用 mt.exe 会破坏它们:stackoverflow.com/a/14654743 -- 你知道另一种方法吗?
  • 您可以尝试在源可执行文件中嵌入清单,然后将其与压缩应用程序连接。

标签: python windows pyinstaller manifest max-path


【解决方案1】:

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

(Windows) 在构建的应用程序清单中启用 longPathAware 选项,以支持 Windows 10 v.1607 及更高版本上的长文件路径。 (#5424)

【讨论】:

    猜你喜欢
    • 2018-04-19
    • 1970-01-01
    • 1970-01-01
    • 2012-12-12
    • 1970-01-01
    • 2012-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多