Включение поддержки длинных путей файлов Windows в приложении PyInstaller - PullRequest
1 голос
/ 15 января 2020

У меня проблема со скриптом, который я встроил в исполняемый файл с помощью 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, согласно changelog и PR # 3746 :

  • (Windows) Fix UA C в одном режим файла путем встраивания манифеста. ( # 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 не делает то, что я думаю, что должен? Это ошибка?

Этот ответ описывает изменение исходного кода PyInstaller для переопределения создания встроенного манифеста. Это все еще необходимо?

Я также натолкнулся на проект на GitHub, который, похоже, имеет ту же проблему; автор этого PR заявляет:

Обратите внимание, что PyInstaller еще не понимает настройку longPathAware и удаляет ее из манифеста.

Я не знаю, правда ли это, но я думаю, что это придает некоторый вес этой ошибке.

Я использую PyInstaller 3.6, Python 3.7.2 и Windows 10 версии 1809

...