Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compiling an IronPython WPF project to exe

Tags:

What is the best way to pack up an IronPython application for deployment? After scouring the web the best thing I've come up with (and what I'm currently doing) is using clr.CompileModules() to glue together my entire project's .py files into one .dll, and then having a single run.py do this to run the dll:

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

This is still suboptimal, though, because it means I have to

  1. distribute 3 files (the .dll, the .xaml, and the run.py launcher)
  2. install IronPython on the host machine

Plus, this feels so... hacky, after the wonderful integration IronPython already has with Visual Studio 2010. I'm completely mystified as to why there is no integrated build system for IPy apps, seeing as it all boils down to IL anyway.

Ideally, I want to be able to have a single .exe with the .xaml merged inside somehow (I read that C# apps compile XAML to BAML and merge them in the executable), and without requiring IronPython to be installed to run. Is this at least halfway possible? (I suppose it's ok if the exe needs some extra .DLLs with it or something. The important part is that it's in .exe form.)


Some edits to clarify: I have tried pyc.py, but it seems to not acknowledge the fact that my project is not just app.py. The size of the exe it produces suggests that it is just 'compiling' app.py without including any of the other files into the exe. So, how do I tell it to compile every file in my project?

To help visualize this, here is a screenshot of my project's solution explorer window.


Edit II: It seems that unfortunately the only way is to use pyc.py and pass every single file to it as a parameter. There are two questions I have for this approach:

  1. How do I possibly process a command line that big? There's a maximum of 256 characters in a command.
  2. How does pyc.py know to preserve the package/folder structure? As shown in my project screenshot above, how will my compiled program know to access modules that are in subfolders, such as accessing DT\Device? Is the hierarchy somehow 'preserved' in the dll?

Edit III: Since passing 70 filenames to pyc.py through the command line will be unwieldy, and in the interest of solving the problem of building IPy projects more elegantly, I've decided to augment pyc.py.

I've added code that reads in a .pyproj file through the /pyproj: parameter, parses the XML, and grabs the list of py files used in the project from there. This has been working pretty well; however, the executable produced seems to be unable to access the python subpackages (subfolders) that are part of my project. My version of pyc.py with my .pyproj reading support patch can be found here: http://pastebin.com/FgXbZY29

When this new pyc.py is run on my project, this is the output:

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 

So it correctly read in the list of files in the .pyproj... Great! But running the exe gives me this:

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

So even though Cu64\ui.py is obviously included in compilation, the exe, when run, can't find it. This is what I was afraid of in point #2 in the previous edit. How do I preserve the package hierarchy of my project? Perhaps compiling each package seperately may be needed?

I'll extend the bounty for this question. Ultimately my hope is that we can get a working pyc.py that reads in pyproj files and produces working exes in one step. Then maybe it could even be submitted to IronPython's codeplex to be included in the next release... ;]

like image 394
Aphex Avatar asked Oct 22 '10 17:10

Aphex


People also ask

Can you use Python with WPF?

Oh, yes, IronPython and Telerik UI for WPF are a match made in heaven that will bring your Python desktop application to the next level.


2 Answers

Use pyc.py to produce app.exe and don't forget to include app.dll and IronPython libraries.

As for XAML - I've created project just for .xaml files that I compile in VS and then use them from IronPython. For example:

<ResourceDictionary.MergedDictionaries>   <ResourceDictionary Source="/CompiledStyle;component/Style.xaml" />  </ResourceDictionary.MergedDictionaries>  
like image 193
Lukas Cenovsky Avatar answered Sep 18 '22 19:09

Lukas Cenovsky


It "boils down to IL", but it isn't compatible with the IL that C# code produces, so it can't be directly compiled to a standalone .exe file. You'll need to use pyc.py to compile your code to a stub EXE with the DLL that CompileModules creates. Then distribute those files with IronPython.dll, IronPython.Modules.dll, Microsoft.Dynamic.dll, Microsoft.Scripting.Debugging.dll, Microsoft.Scripting.dll, and of course the XAML file.

To compile other files, just add them as arguments: ipy.exe pyc.py /main:app.py /target:winexe another.py another2.py additional.py

like image 34
jcao219 Avatar answered Sep 17 '22 19:09

jcao219