【问题标题】:IronPython: EXE compiled using pyc.py cannot import module "os"IronPython:使用 pyc.py 编译的 EXE 无法导入模块“os”
【发布时间】:2011-06-01 02:57:08
【问题描述】:

我有一个简单的 IronPython 脚本:

# Foo.py
import os

def main():
    print( "Hello" )

if "__main__" == __name__:
    main()

如果我使用 IronPython 运行它,它运行良好并打印 Hello

ipy Foo.py

按照 IronPython - how to compile exe 中给出的说明,我使用以下代码将 IronPython 脚本编译为 EXE:

ipy pyc.py /main:Foo.py /target:exe

执行 Foo.exe 出现此错误:

Unhandled Exception: IronPython.Runtime.Exceptions.ImportException: No module named os
   at Microsoft.Scripting.Runtime.LightExceptions.CheckAndThrow(Object value)
   at DLRCachedCode.__main__$1(CodeContext $globalContext, FunctionCode $functionCode)
   at IronPython.Compiler.OnDiskScriptCode.Run()
   at IronPython.Compiler.OnDiskScriptCode.Run(Scope scope)
   at IronPython.Runtime.PythonContext.InitializeModule(String fileName, ModuleContext moduleContext, ScriptCode scriptC
ode, ModuleOptions options)

为什么找不到模块“os”?我该如何解决这个问题,这样我才能获得一个正常工作的 EXE?

(请注意,这与问题 IronPython cannot import module os 不同,因为如果我使用 ipy.exe 运行,脚本可以正常工作。)

【问题讨论】:

    标签: python ironpython


    【解决方案1】:

    构建一个您可以分发的 Ironpython EXE 有点棘手——尤其是在您使用标准库的元素时。我的典型解决方案如下:

    我将我需要的所有 stdlib 模块复制到一个文件夹中(通常所有这些模块只是为了完整性)并使用这个脚本来构建我的 exe。在这个例子中,我有两个文件 FredMain.pyFredSOAP.py 被编译成一个名为 Fred_Download_Tool

    的 EXE
    import sys
    sys.path.append(r'C:\Program Files\IronPython 2.7\Lib')
    sys.path.append(r'C:\Program Files\IronPython 2.7')
    import clr
    
    clr.AddReference('IronPython')
    clr.AddReference('IronPython.Modules')
    clr.AddReference('Microsoft.Scripting.Metadata')
    clr.AddReference('Microsoft.Scripting')
    clr.AddReference('Microsoft.Dynamic')
    clr.AddReference('mscorlib')
    clr.AddReference('System')
    clr.AddReference('System.Data')
    
    #
    # adapted from os-path-walk-example-3.py
    
    import os, glob
    import fnmatch
    import pyc
    
    def doscopy(filename1):
        print filename1
        os.system ("copy %s .\\bin\Debug\%s" % (filename1, filename1))
    
    class GlobDirectoryWalker:
        # a forward iterator that traverses a directory tree
    
        def __init__(self, directory, pattern="*"):
            self.stack = [directory]
            self.pattern = pattern
            self.files = []
            self.index = 0
    
        def __getitem__(self, index):
            while 1:
                try:
                    file = self.files[self.index]
                    self.index = self.index + 1
                except IndexError:
                    # pop next directory from stack
                    self.directory = self.stack.pop()
                    self.files = os.listdir(self.directory)
                    self.index = 0
                else:
                    # got a filename
                    fullname = os.path.join(self.directory, file)
                    if os.path.isdir(fullname) and not os.path.islink(fullname) and fullname[-4:]<>'.svn':
                        self.stack.append(fullname)
                    if fnmatch.fnmatch(file, self.pattern):
                        return fullname
    
    #Build StdLib.DLL
    gb = glob.glob(r".\Lib\*.py")
    gb.append("/out:StdLib")    
    
    #print ["/target:dll",]+gb
    
    pyc.Main(["/target:dll"]+gb)
    
    #Build EXE
    gb=["/main:FredMain.py","FredSOAP.py","/target:exe","/out:Fred_Download_Tool"]
    pyc.Main(gb)
    
    
    #CopyFiles to Release Directory
    doscopy("StdLib.dll")
    doscopy("Fred_Download_Tool.exe")
    doscopy("Fred_Download_.dll")
    
    
    #Copy DLLs to Release Directory
    fl = ["IronPython.dll","IronPython.Modules.dll","Microsoft.Dynamic.dll","Microsoft.Scripting.Debugging.dll","Microsoft.Scripting.dll","Microsoft.Scripting.ExtensionAttribute.dll","Microsoft.Scripting.Core.dll"]
    for f in fl:
    
    doscopy(f)
    

    当我准备好编译时,我会在我的脚本中添加以下内容。这允许程序使用我的 DLL 中的标准模块而不是 Python 安装。如果你想分发给没有安装 Python 的人,这是必要的。只需确保在创建安装程序时包含必要的 DLL。

    #References to created DLL of python modules
    clr.AddReference('StdLib')
    

    【讨论】:

    • 是的,编译 IronPython 的 Lib 目录中的所有内容并从正在编译的脚本中引用生成的 DLL 对我来说是诀窍。在 pyc.py 的较新版本(我猜)中还有一个 /standalone 选项可以自动将 IronPython 的核心 dll 编译到生成的 exe 中
    • /standalone 选项目前似乎不起作用 - 我仍然需要将 *.dll 从 ironpython 的目录复制到我的 exe 位置
    • 这对我来说很难。请逐步详细说明
    【解决方案2】:

    我知道这个问题已经回答了很长时间,但我仍然需要很长时间才能让我的 exe 正常工作。我指出了 5 条错误消息,其中存在此​​导入问题。这就是我必须做的让我的 exe 工作:

    1) 在部署文件夹中包含所有 IronPython dll(IronPython.dll、IronPython.Modules.dll 等)

    2) 在 deploye 文件夹中包含标准库中的 dll

    3)你的exe所在的路径不能有空格

    (这个: C:\User1\MyDocuments\我的文件夹\deployFolder

    应该改为例如: C:\User1\MyDocuments\MyFolder\deployFolder)

    4) 您的操作系统可能会阻止您的 exe 文件使用的 dll 并给您“loadFromRemoteResource 交换器错误 blablabla”。要解决这个问题,您需要右键单击 dll 并在窗口的最后一行按“取消阻止”。

    5) 最后别忘了在你的exe文件中包含pyc给出的dll文件(同名,只是扩展名不同)

    如果您需要,这是我写的更详细的文章:http://thesesergio.wordpress.com/2013/09/11/how-to-generate-and-use-a-exe-that-uses-net-dlls-with-ironpython-pyc-py/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-01-27
      • 2019-08-17
      • 2019-02-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多