IronPython: EXE compiled using pyc.py cannot import module "os"

15,664

Solution 1

Building an Ironpython EXE that you can distribute is a bit tricky - especially if you are using elements of the standard library. My typical solution is the following:

I copy all of the stdlib modules I need into a folder (usually all of them just for completeness) and use this script to build my exe. In this example I have two files FredMain.py and FredSOAP.py that get compiled into an EXE called Fred_Download_Tool

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)

In my scripts I add the following when I am ready to compile. This allows the program to use the Standard Modules from my DLL instead of the Python Install. This is necessary if you want to distribute to people without Python installed. Just make sure you include the necessary DLL's when you create your installer.

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

Solution 2

I know this has been answered for a long time but it still took me a LOT of time to get my exe working. I pointed out 5 error messages among which there was this import issue. This is what I had to do to make my exe work :

1) include all IronPython dlls in the deploy folder (IronPython.dll, IronPython.Modules.dll etc.)

2) include dlls from the standard library in the deploye folder

3) the path where your exe is located should have no space

(this : C:\User1\MyDocuments\My Folder\deployFolder

should be changed to that for instance : C:\User1\MyDocuments\MyFolder\deployFolder)

4) your os may block a dll used by your exe file and give you a "loadFromRemoteResource comutator error blablabla". To fix that you need to right click on the dll and press "unblock" on the last line of the Window.

5) finally don't forget to include the dll file given by pyc with your exe file (same name, only a difference in the extension)

Here is an article I wrote with more details if you need it : http://thesesergio.wordpress.com/2013/09/11/how-to-generate-and-use-a-exe-that-uses-net-dlls-with-ironpython-pyc-py/

Share:
15,664

Related videos on Youtube

Markus Joschko
Author by

Markus Joschko

I work with GPUs on deep learning and computer vision.

Updated on April 24, 2020

Comments

  • Markus Joschko
    Markus Joschko about 4 years

    I have a simple IronPython script:

    # Foo.py
    import os
    
    def main():
        print( "Hello" )
    
    if "__main__" == __name__:
        main()
    

    It runs fine and prints Hello if I run it with IronPython as:

    ipy Foo.py
    

    Following the instructions given in IronPython - how to compile exe, I compiled this IronPython script to a EXE using:

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

    Executing Foo.exe gives this error:

    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)
    

    Why cannot module "os" be found? How do I fix this, so I can get a working EXE?

    (Note that this is different from the question IronPython cannot import module os since the script works fine if I run with ipy.exe.)

  • hello_earth
    hello_earth over 9 years
    yes, compiling everything in IronPython's Lib directory and referencing the resulting DLL from the script being compiled did the trick for me. there is also a /standalone option in the newer version (i guess) of pyc.py to compile IronPython's core dll into the resulting exe automatically
  • hello_earth
    hello_earth over 9 years
    /standalone option doesn't seem to work at the moment - i still need to copy *.dll from ironpython's directory to my exe location
  • SaeHyun Kim
    SaeHyun Kim almost 7 years
    It's hard for me. Plz more detail step by step