Подтвердить что ты не робот

Компиляция проекта WPF IronPython для exe

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

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

import app

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

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

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

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


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

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


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

  • Как я могу обработать большую командную строку? В команде должно быть не более 256 символов.
  • Как 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, очевидно, включен в компиляцию, exe при запуске не может его найти. Это то, чего я боялся в пункте № 2 в предыдущем редактировании. Как сохранить иерархию пакетов моего проекта? Возможно, может понадобиться компиляция каждого пакета?

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

4b9b3361

Ответ 1

Он "сводится к IL", но он несовместим с IL, который производит код С#, поэтому его нельзя напрямую скомпилировать в автономный .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

Ответ 2

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

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

<ResourceDictionary.MergedDictionaries>
  <ResourceDictionary Source="/CompiledStyle;component/Style.xaml" /> 
</ResourceDictionary.MergedDictionaries> 

Ответ 3

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

Ответ 4

Чтобы создать набор сборок для приложения 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.

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

Ответ 5

Я установил Visual Studio 2015 с PTVS (ironpython 2.7). Я создал очень простой проект WPF и не смог скомпилировать exe. Я всегда получал исключение "ImportError: No module 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. Шаги для его компиляции:

  • установить pip для CPython 2.7 (не ironpython!)

  • установить ipy2asm

python -m pip install ironpycompiler

  1. скомпилируйте приложение, например

ipy2asm компилировать -t winexe -e -s program.py