Компиляция проекта IronPython WPF для exe - PullRequest
22 голосов
/ 22 октября 2010

Каков наилучший способ упаковки приложения IronPython для развертывания? После просмотра веб-страниц лучшее, что я придумал (и то, что я сейчас делаю), это использование clr.CompileModules() для склейки файлов .py всего моего проекта в одну .dll, а затем использование одного run.py do это для запуска DLL:

import clr
clr.AddReference('compiledapp.dll')

import app

Это все еще неоптимально, потому что это означает, что я должен

  1. распространяет 3 файла (.dll, .xaml и run.py launcher)
  2. установить IronPython на хост-машину

Плюс, это выглядит так ... хакерски, после замечательной интеграции IronPython с Visual Studio 2010. Я совершенно не понимаю, почему не существует интегрированной системы сборки для приложений IPy, поскольку все сводится к ИЛ в любом случае.

В идеале я хочу иметь возможность объединить один .exe с .xaml внутри (я читал, что приложения C # компилируют XAML в BAML и объединяют их в исполняемый файл), и при этом не требуется установка IronPython бежать. Возможно ли это хотя бы на полпути? (Я полагаю, что все в порядке, если exe-файл нуждается в дополнительных .DLL с ним или чем-то еще. Важной частью является то, что он находится в форме .exe.)


Некоторые правки, чтобы уточнить: Я пробовал pyc.py , но, похоже, не признает тот факт, что мой проект не просто app.py. Размер исполняемого файла предполагает, что он просто «компилирует» app.py без включения каких-либо других файлов в исполняемый файл. Итак, как мне сказать, чтобы компилировать каждый файл в моем проекте?

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


Редактировать II: Кажется, что, к сожалению, единственный способ - использовать pyc.py и передавать каждый отдельный файл в качестве параметра. У меня есть два вопроса для этого подхода:

  1. Как мне обработать такую ​​большую командную строку? В команде максимум 256 символов.
  2. Как pyc.py узнает, как сохранить структуру пакета / папки? Как показано на скриншоте моего проекта выше, как моя скомпилированная программа узнает, как получить доступ к модулям, которые находятся в подпапках, например, получить доступ к DT \ Device? Сохранена ли иерархия как-то в dll?

Редактировать III : Поскольку передача 70 имен файлов в pyc.py через командную строку будет громоздкой, и в интересах более элегантного решения проблемы создания проектов IPy, я решил дополнить pyc.py.

Я добавил код, который читает файл .pyproj через параметр /pyproj:, анализирует XML и получает оттуда список py-файлов, используемых в проекте. Это работает довольно хорошо; однако производимый исполняемый файл, похоже, не может получить доступ к подпакетам (подпапкам) Python, которые являются частью моего проекта. Моя версия pyc.py с моим патчем поддержки чтения .pyproj может быть найдена здесь: http://pastebin.com/FgXbZY29

Когда этот новый pyc.py запущен в моем проекте, это вывод:

c:\Projects\GenScheme\GenScheme>"c:\Program Files (x86)\IronPython 2.7\ipy.exe"
pyc.py /pyproj:GenScheme.pyproj /out:App /main:app.py /target:exe
Input Files:
        c:\Projects\GenScheme\GenScheme\__init__.py
        c:\Projects\GenScheme\GenScheme\Agent.py
        c:\Projects\GenScheme\GenScheme\AIDisplay.py
        c:\Projects\GenScheme\GenScheme\app.py
        c:\Projects\GenScheme\GenScheme\BaseDevice.py
        c:\Projects\GenScheme\GenScheme\BaseManager.py
        c:\Projects\GenScheme\GenScheme\BaseSubSystem.py
        c:\Projects\GenScheme\GenScheme\ControlSchemes.py
        c:\Projects\GenScheme\GenScheme\Cu64\__init__.py
        c:\Projects\GenScheme\GenScheme\Cu64\agent.py
        c:\Projects\GenScheme\GenScheme\Cu64\aidisplays.py
        c:\Projects\GenScheme\GenScheme\Cu64\devmapper.py
        c:\Projects\GenScheme\GenScheme\Cu64\timedprocess.py
        c:\Projects\GenScheme\GenScheme\Cu64\ui.py
        c:\Projects\GenScheme\GenScheme\decorators.py
        c:\Projects\GenScheme\GenScheme\DeviceMapper.py
        c:\Projects\GenScheme\GenScheme\DT\__init__.py
        c:\Projects\GenScheme\GenScheme\DT\Device.py
        c:\Projects\GenScheme\GenScheme\DT\Manager.py
        c:\Projects\GenScheme\GenScheme\DT\SubSystem.py
        c:\Projects\GenScheme\GenScheme\excepts.py
        c:\Projects\GenScheme\GenScheme\FindName.py
        c:\Projects\GenScheme\GenScheme\GenScheme.py
        c:\Projects\GenScheme\GenScheme\PMX\__init__.py
        c:\Projects\GenScheme\GenScheme\PMX\Device.py
        c:\Projects\GenScheme\GenScheme\PMX\Manager.py
        c:\Projects\GenScheme\GenScheme\PMX\SubSystem.py
        c:\Projects\GenScheme\GenScheme\pyevent.py
        c:\Projects\GenScheme\GenScheme\Scheme.py
        c:\Projects\GenScheme\GenScheme\Simulated\__init__.py
        c:\Projects\GenScheme\GenScheme\Simulated\Device.py
        c:\Projects\GenScheme\GenScheme\Simulated\SubSystem.py
        c:\Projects\GenScheme\GenScheme\speech.py
        c:\Projects\GenScheme\GenScheme\stdoutWriter.py
        c:\Projects\GenScheme\GenScheme\Step.py
        c:\Projects\GenScheme\GenScheme\TimedProcess.py
        c:\Projects\GenScheme\GenScheme\UI.py
        c:\Projects\GenScheme\GenScheme\VirtualSubSystem.py
        c:\Projects\GenScheme\GenScheme\Waddle.py
Output:
        App
Target:
        ConsoleApplication
Platform:
        ILOnly
Machine:
        I386
Compiling...
Saved to App

Так что правильно читайте в списке файлов в .pyproj ... Отлично! Но запуск exe дает мне это:

Unhandled Exception: IronPython.Runtime.Exceptions.ImportException: 
No module named Cu64.ui

Так что, хотя Cu64\ui.py явно включен в компиляцию, исполняемый файл не может его найти. Это то, чего я боялся в пункте № 2 в предыдущем редактировании. Как мне сохранить иерархию пакетов моего проекта? Возможно, может потребоваться отдельная компиляция каждого пакета?

Я продлю награду за этот вопрос. В конечном счете, я надеюсь, что мы сможем получить рабочий pyc.py, который читает файлы pyproj и создает рабочие exe за один шаг. Тогда, может быть, он даже может быть отправлен в кодовый комплекс IronPython для включения в следующий выпуск ...;]

Ответы [ 5 ]

5 голосов
/ 08 марта 2012

Я опубликовал скрипт на Python, который может взять файл IronPython, выяснить его зависимости и скомпилировать пакет в отдельный двоичный файл по адресу Ironpython 2.6 .py -> .exe .Надеюсь, что вы найдете ее полезной.Он должен работать и для WPF, так как он включает поддержку WPF.

5 голосов
/ 23 октября 2010

Используйте pyc.py для получения app.exe и не забудьте включить библиотеки app.dll и IronPython.

Что касается XAML - я создал проект только для .xaml файлов, которые я компилируюв VS, а затем использовать их из IronPython.Например:

<ResourceDictionary.MergedDictionaries>
  <ResourceDictionary Source="/CompiledStyle;component/Style.xaml" /> 
</ResourceDictionary.MergedDictionaries> 
5 голосов
/ 22 октября 2010

Он «сводится к IL», но он не совместим с IL, создаваемым кодом C #, поэтому он не может быть напрямую скомпилирован в отдельный файл .exe. Вам нужно будет использовать pyc.py для компиляции кода в заглушку EXE с DLL, которую создает CompileModules. Затем распространите эти файлы с IronPython.dll, IronPython.Modules.dll, Microsoft.Dynamic.dll, Microsoft.Scripting.Debugging.dll, Microsoft.Scripting.dll и, конечно же, файлом XAML.

Чтобы скомпилировать другие файлы, просто добавьте их в качестве аргументов: ipy.exe pyc.py /main:app.py /target:winexe another.py another2.py additional.py

3 голосов
/ 31 октября 2010

Чтобы создать набор сборок для вашего приложения IronPython, чтобы вы могли распространять его, вы можете использовать pyc.py или SharpDevelop.

Для компиляции с использованием pyc.py:

ipy.exe pyc.py /main:Program.py Form.py File1.py File2.py ... / target: winexe

Учитывая количество файлов в вашем проекте, вы можете попробовать использовать SharpDevelop вместо поддержки длинной командной строки для pyc.py. Вам нужно будет создать новый проект IronPython в SharpDevelop и импортировать ваши файлы в проект. Вероятно, вам придется импортировать файлы по одному, поскольку в SharpDevelop нет способа импортировать несколько файлов, если они не находятся во вложенной папке.

Затем вы можете использовать SharpDevelop, чтобы скомпилировать ваше приложение в исполняемый файл и DLL. Все остальные необходимые файлы, такие как IronPython.dll, Microsoft.Scripting.dll, будут находиться в папке bin / debug или bin / release. SharpDevelop использует clr.CompileModules и пользовательскую задачу MSBuild для создания двоичных файлов.

Любые пакеты IronPython, определенные в вашем проекте, должны использоваться из вашего приложения после компиляции.

Упаковка XAML может быть сделана путем встраивания xaml в качестве ресурса. Затем с помощью кода, аналогичного следующему:

import clr

clr.AddReference('PresentationFramework')
clr.AddReference('System')

from System.IO import FileMode, FileStream, Path
from System.Reflection import Assembly
from System.Windows import Application
from System.Windows.Markup import XamlReader

executingAssemblyFileName = Assembly.GetEntryAssembly().Location
directory = Path.GetDirectoryName(executingAssemblyFileName)
xamlFileName = Path.Combine(directory, "Window1.xaml")

stream = FileStream(xamlFileName, FileMode.Open)
window = XamlReader.Load(stream)
app = Application()
app.Run(window)

SharpDevelop 3.2 неправильно встраивает файлы ресурсов, поэтому вам нужно использовать SharpDevelop 4.

Если вы используете IronPython 2.7, вы можете использовать новый метод clr.LoadComponent, который принимает объект и либо имя файла XAML, либо поток и связывает этот объект с XAML.

Хотя компилятор C # может скомпилировать ваш XAML в ресурс BAML, то же самое с IronPython имеет несколько проблем. Если вы не связываете XAML с классом через атрибут x: Class, то можно скомпилировать XAML в ресурс BAML и встроить его в вашу сборку. Однако вы не получите автоматически сгенерированный код, поэтому вам придется создавать этот код самостоятельно. Другая проблема заключается в том, что это не будет работать из коробки с SharpDevelop. Вам нужно будет отредактировать файл SharpDevelop.Build.Python.targets и изменить его с Python на C #. Попытка использовать атрибут x: Class не будет работать, так как читатель BAML не может получить доступ к любому связанному классу IronPython. Это связано с тем, что сгенерированный IL в скомпилированном приложении IronPython сильно отличается от такового в сборке C # или VB.NET.

2 голосов
/ 18 декабря 2015

Я установил Visual Studio 2015 с PTVS (Ironpython 2.7).Я создал очень простой проект WPF и не смог скомпилировать exe.Я всегда получал исключение «ImportError: нет модуля с именем wpf».

import clr
clr.AddReferenceToFileAndPath("c:\\path\\to\\IronPython.Wpf.dll")
clr.AddReferenceToFileAndPath('c:\\path\\to\\PresentationCore.dll')
clr.AddReferenceToFileAndPath('c:\\path\\to\\PresentationFramework.dll')
clr.AddReferenceToFileAndPath('c:\\path\\to\\WindowsBase.dll')

from System.Windows import Application, Window

import wpf

class MyWindow(Window):
    def __init__(self):
        wpf.LoadComponent(self, 'RegExTester.xaml')

    def OnSearch(self, sender, e):
        self.tbOut.Text = "hello world"

if __name__ == '__main__':
    Application().Run(MyWindow())

Ошибка, которую я получил, состояла в том, что предложение clr должно быть перед импортом wpf.Шаги для его компиляции:

  1. установка pip для CPython 2.7 (не ironpython!)

  2. установка ipy2asm

python -m pip install ironpycompiler

скомпилировать приложение как

ipy2asm compile -t winexe -e -s program.py

...