2010-10-22 183 views
22

打包IronPython應用程序以進行部署的最佳方式是什麼?在瀏覽網頁後,我想到的最好的東西(以及我目前正在做的)是使用clr.CompileModules()將我整個項目的.py文件粘貼到一個.dll文件中,然後使用一個run.py來執行此操作DLL:將IronPython WPF項目編譯爲exe

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

import app 

這仍然是最理想的,但是,因爲這意味着我必須

  1. 分發3個文件(.dll.xamlrun.py發射)
  2. 上安裝IronPython的主機

另外,這感覺很......哈克,精彩整合後的IronPython已經與Visual Studio 2010中,我以爲什麼有IPY的應用程序沒有集成構建系統完全被迷惑,看到這一切無論如何,它歸結爲IL。

理想情況下,我希望能夠有一個.exe.xaml合併內以某種方式(我讀的C#應用​​程序編譯XAML來BAML和可執行合併它們),並且不需要進行安裝IronPython的運行。這至少有一半可能嗎? (我想這是確定的,如果exe文件需要用它或東西一些額外的.DLL文件最重要的部分是它的以.exe形式。)


有些修改,以澄清:我已經試過PYC。 py,但它似乎不承認我的項目不只是app.py。它產生的exe的大小表明它只是在編譯'app.py而不包含任何其他文件到exe中。那麼,我該如何告訴它來編譯我的項目中的每個文件?

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


編輯II:看來,不幸的是,唯一的辦法就是使用pyc.py並通過每一個文件把它作爲一個參數。這個方法有兩個問題:

  1. 我該如何處理一個大的命令行?命令中最多有256個字符。
  2. pyc.py如何知道如何保留包/文件夾結構?如上面我的項目屏幕截圖所示,我的編譯程序如何知道訪問子文件夾中的模塊,比如訪問DT \ Device?這個層次結構是否「保存」在dll中?

編輯III:由於經過70名到pyc.py通過命令行會笨重,以及解決更優雅建築IPY項目的問題的興趣,我決定增加pyc.py

我已經添加了通過/pyproj:參數讀取.pyproj文件的代碼,解析XML,並從那裏獲取項目中使用的py文件列表。這一直工作得很好;但是,生成的可執行文件似乎無法訪問作爲我的項目一部分的python子包(子文件夾)。我與我的.pyproj閱讀支持補丁pyc.py版本可以在這裏找到: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運行時,無法找到它。這是我在之前的編輯中第二點中所害怕的。我如何保留我的項目的包層次結構?也許需要分別編譯每個軟件包?

我會延長這個問題的賞金。最終,我的希望是,我們可以得到一個可讀取pyproj文件的工作pyc.py,並一步完成工作。那麼它可能甚至會被提交給IronPython的codeplex以包含在下一個版本中...;]

+1

命令行長度爲8191個字符(http://support.microsoft.com/kb/830473)。 'clr.CompileModules'很好地處理了包 - 它通過'__init __。py'識別它們,就像通常用於Python包一樣。 – 2010-10-28 15:38:12

+0

是的,您可以使用clr.CompileModules,然後生成加載.dll的存根.exe文件。我認爲有一個LoadAssembly函數可以在C#中使用。 – jcao219 2010-10-28 21:04:59

+0

啊 - 我的意思是'pyc.py'使用'clr.CompileModules'來處理軟件包。所以只需使用pyc.py,它應該可以工作;-) – 2010-10-29 00:30:29

回答

5

它「歸結爲IL」,但它與C#代碼生成的IL不兼容,所以它不能直接編譯爲獨立的.exe文件。 您需要使用pyc.py將代碼編譯爲帶有CompileModules創建的DLL的存根EXE。 然後分配這些文件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

+0

非常有趣。我會再次嘗試pyc.py。 – Aphex 2010-10-22 20:07:16

+0

'ipy.exe pyc.py/main:app.py/target:winexe'產生一個小小的3kb App.exe,它什麼都不做。我還需要在這裏做些什麼嗎? – Aphex 2010-10-22 20:09:26

+0

它也生產app.dll。用前面提到的那些dll和你的XAML文件分發它。 – jcao219 2010-10-22 22:29:48

5

使用pyc.py生產app.exe,不要忘了,包括app.dll和IronPython庫。

至於XAML - 我創建的項目僅適用於在VS中編譯的.xaml文件,然後在IronPython中使用它們。例如:

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

好吧,我已經與pyc.py而且我還不知道如何使它使用我需要的所有文件。我的項目包含5個文件夾中的78個文件,並通過運行app.py啓動;然而,正如我在jcao219中對運行'ipy.exe pyc.py /main:app.py/target:quotexe'的註釋中提到的那樣,產生了一個無用的app.exe,它在啓動時不會執行任何操作。 – Aphex 2010-10-26 19:29:07

+0

我建議你從簡單的Hello World應用開始。試圖使78個文件工作太多。從一個文件開始,添加另一個文件,然後添加子文件夾等。當您通過簡單啓動時,您的應用程序也會運行:'ipy.exe app.py'? – 2010-10-27 19:32:23

+0

是的,'ipy.exe app.py'運行良好。順便說一下,我在第一篇文章中添加了當前項目結構的屏幕截圖...我開始認爲我需要將所有文件作爲命令行參數提供給pyc.py。這真的**是我應該構建和發佈我的IPy應用程序的方式嗎?在這裏輸入'ipy.exe pyc.py app.py <78 .py文件> /main:app.py/target:winexe'? – Aphex 2010-10-27 20:47:28

3

要創建一套爲您的IronPython的應用程序組件,讓您可以分發您可以使用pyc.py或SharpDevelop的。

編譯使用pyc.py:

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

鑑於量您可以嘗試使用SharpDevelop而不是維護pyc.py的長命令行。您需要在SharpDevelop中創建一個新的IronPython項目並將您的文件導入到項目中。您可能需要一次導入一個文件,因爲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一樣,它有一些問題。如果您不通過x:Class屬性將XAML鏈接到類,則可以將XAML編譯爲BAML資源並將其嵌入到程序集中。但是,您不會得到任何自動生成的代碼,因此您需要自己創建該代碼。另一個問題是,這不會使用SharpDevelop。您需要編輯SharpDevelop.Build.Python.targets文件並將Python從Python更改爲C#。嘗試使用x:Class屬性將不起作用,因爲BAML閱讀器無法訪問任何關聯的IronPython類。這是因爲編譯的IronPython應用程序中生成的IL與C#或VB.NET程序集中的生成的IL非常不同。

+0

感謝您對SharpDevelop的評論。儘管我很討厭從Visual Studio 2010移植到不同的IDE,但這可能是一些嘗試。查看我最近編輯的一些信息,瞭解我一直在做什麼來讓pyc閱讀我所有的文件;我真的很接近它的工作。 – Aphex 2010-11-01 20:41:36

5

我發佈了一個Python腳本,它可以接收一個IronPython文件,找出它的依賴關係,並將它編譯成一個獨立的二進制文件Ironpython 2.6 .py -> .exe。希望你覺得它有用。它也應該爲WPF工作,因爲它捆綁了WPF支持。

2

我用PTVS(ironpython 2.7)安裝了Visual Studio 2015。我創建了一個非常簡單的WPF項目,但無法編譯exe文件。我總是得到異常「ImportError:No module named 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