打包IronPython应用程序进行部署的最佳方法是什么?在浏览网页后,我提出的最好的事情(以及我目前正在做的事情)是使用clr.CompileModules()
将我整个项目的.py文件粘合到一个.dll中,然后使用单个{{ 1}}这样做来运行dll:
run.py
但这仍然不是最理想的,因为这意味着我必须
import clr
clr.AddReference('compiledapp.dll')
import app
,.dll
和.xaml
启动器)另外,在IronPython与Visual Studio 2010进行了精彩的整合之后,感觉如此...... hacky。我完全不知道为什么没有针对IPy应用程序的集成构建系统,因为这一切都归结为IL无论如何。
理想情况下,我希望能够以某种方式将run.py
与.exe
内部合并(我读到C#apps将XAML编译为BAML并将其合并到可执行文件中),并且不需要要安装IronPython才能运行。这至少有一半可能吗? (我想如果exe需要一些额外的.DLL或者其他东西就可以了。重要的是它是.exe形式。)
有些修改要澄清:我已经尝试了 pyc.py ,但似乎并不承认我的项目不只是.xaml
。它产生的exe的大小表明它只是“编译”app.py
而不包含任何其他文件到exe中。那么,我如何告诉它编译我的项目中的每个文件?
To help visualize this, here is a screenshot of my project's solution explorer window.
编辑II:不幸的是,似乎唯一的方法是使用app.py
并将每个文件作为参数传递给它。我对这种方法有两个问题:
编辑III :由于通过命令行将70个文件名传递给pyc.py
将是不实用的,为了解决更优雅地构建IPy项目的问题,我已经决定了增加pyc.py
。
我添加了通过pyc.py
参数读入.pyproj
文件的代码,解析XML,并从那里获取项目中使用的py文件列表。这一直很好;但是,生成的可执行文件似乎无法访问属于我的项目的python子包(子文件夹)。我的/pyproj:
版本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。那么也许它甚至可以提交给IronPython的codeplex以包含在下一个版本中......;]
答案 0 :(得分: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
答案 1 :(得分:5)
使用pyc.py
生成app.exe
,不要忘记包含app.dll
和IronPython库。
对于XAML - 我为.xaml
文件创建了项目,我在VS中编译然后在IronPython中使用它们。例如:
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/CompiledStyle;component/Style.xaml" />
</ResourceDictionary.MergedDictionaries>
答案 2 :(得分:5)
我发布了一个Python脚本,它可以获取IronPython文件,找出它的依赖关系并将该批次编译成Ironpython 2.6 .py -> .exe的独立二进制文件。希望你觉得它有用。它应该也适用于WPF,因为它捆绑了WPF支持。
答案 3 :(得分:3)
要为IronPython应用程序创建一组程序集以便分发它,您可以使用pyc.py或SharpDevelop。
使用pyc.py进行编译:
ipy.exe pyc.py /main:Program.py Form.py File1.py File2.py ... / target: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从C#更改为C#。尝试使用x:Class属性将无法工作,因为BAML阅读器无法访问任何关联的IronPython类。这是因为已编译的IronPython应用程序中生成的IL与C#或VB.NET程序集中生成的IL非常不同。
答案 4 :(得分:2)
我安装了带有PTVS的Visual Studio 2015(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之前。编译它的步骤: